1

I have a class that I am trying to test out through writing some unit test in C#. I am also using Moq library in my unit test for mocking.

Below are some of the methods in my class which I want to mock so that they can return some dummy data which I want to return always.

public class DataManager
{

    public DataManager(ILoggingService loggingService, IConfiguration configuration)
    {
        // ...
    }

    // how to mock this to return dummy data?
    private DataHolder GetData()
    {
        //... return DataHolder object
    }

    // how to mock this to return dummy data?
    private IEnumerable<ProcessClient> GetClientValues(string value)
    {
        //... return IEnumerable<ProcessClient> object
    }

}

This is how I am testing it out:

    private Mock<ClientUtility> utility;

    [SetUp]
    public void Setup()
    {
        utility = new Mock<ClientUtility>();
    }

    [Test]
    public void Test1()
    {

        // what should I do here so that "GetData" and "GetClientValues" return dummy data when I call below class constructor?
        
        var testName = "config1";
        var testContent = "{}";

        utility.Setup(x => x.Add(new DataStatus { Pin = "test" }, "data.com", "test")).Returns(Task.FromResult(true));
        var dataManager = new DataManager(loggingService.Object, configuration.Object);

        Assert.AreEqual(testContent, dataManager.GetStuff(testName)[0]);
    }

Question:

How can I mock "GetData" and "GetClientValues" using Moq or any other library to return dummy data from those two methods? Is this possible to do?

cs98
  • 129
  • 2
  • 10
  • Normally you would not structure code that way if you plan to write tests (as it is unnecessary hard to do so)... Please clarify if what you are asking is you *actual goal* or just *a way* you decided to take to achieve some other goal. – Alexei Levenkov Aug 04 '20 at 23:55
  • Actually code is like this from starting and I am working on writing unit test so thats why wanted to check on this. I can make them public if it is needed I guess. – cs98 Aug 05 '20 at 00:07
  • How `ClientUtility` class is being used in `DataManager`? – Chetan Aug 05 '20 at 01:41
  • @ChetanRanpariya `ClientUtility` is just a simple class with bunch of methods that `DataManager` class is using internally. – cs98 Aug 07 '20 at 03:34
  • `ClientUtility` is a simple class , but is it used in Datamanager? Why you need to create Mock of it? – Chetan Aug 07 '20 at 07:51

1 Answers1

1

I think you can use CallBase = true. So your mock will behave like true class.

var dataManager = new Mock<DataManager>(loggingService.Object, configuration.Object) { CallBase = true };

dataManager.Object.Method1();
dataManager.Object.Method2();

And you can mock some methods like you do with utility.

Search by "CallBase" on page:

https://github.com/Moq/moq4/wiki/Quickstart

UPDATE I made methods public to call them. And there is some issue, that i didn't see last time. You need to make "virtual" methods if you want change their behavior.

There is example of code. As you can see, GetClientValues() returns real data because we call default real implementation with CallBase = true and GetData() returns dummy data because we mocked its behavior.

public class DataManager
    {

        public DataManager(ILoggingService loggingService, IConfiguration configuration)
        {
            // ...
        }

        // how to mock this to return dummy data?
        public virtual DataHolder GetData()
        {
            return new DataHolder
            {
                Data = "RealData"
            };
        }

        // how to mock this to return dummy data?
        public IEnumerable<ProcessClient> GetClientValues(string value)
        {
            return new List<ProcessClient>
            {
                new ProcessClient
                {
                    Data = "RealData"
                }

            };
        }

    }

And tests.

public class Tests
    {
        [SetUp]
        public void Setup()
        {
        }

        [Test]
        public void Test1()
        {
            var loggingService = new Mock<ILoggingService>();
            var config = new Mock<IConfiguration>();
            var dataManager = new Mock<DataManager>(loggingService.Object, config.Object){CallBase = true};
            dataManager.Setup(x => x.GetData()).Returns(new DataHolder { Data = "FakeData" });

            Assert.AreEqual("RealData", dataManager.Object.GetClientValues("test").First().Data);
            Assert.AreEqual("FakeData", dataManager.Object.GetData().Data);

        }
    }

But anyway i think, that this approach isn't good for testing. There is a problem with testing private methods. We have some ways (for example Invoke()), but in general, "if you want to unit test a private method, something may be wrong". I would like to recommend you to read something about test design and writing testable code. About testing private methods How do you unit test private methods?.

  • thanks for your suggestion. can you provide an example on how can I mock `GetData` and `GetClientValues` method to return some data if possible? still confuse on how `CallBase = true` works here. – cs98 Aug 06 '20 at 15:01
  • I add some examples of code and explanations. I hope it will help you with your problem. If there will be any questions, bring them up :) – Timur Sidoryuk Aug 07 '20 at 04:53