简体   繁体   中英

Mocking a function called by the function you are unit testing. using moq

For example you are testing getSomeString .

public class Class1
{
    public Class1() {}

    public string getSomeString(string input)
    {
        //dosomething

        OtherClass class = new OtherClass();

        return class.getData();
    }
}

public class OtherClass
{
    public OtherClass() {/*some data*/}    

    public string getData()
    {
        //do something

        string aString = getAString(Input);

        //do something
    }

    public virtual string getAString(string input);
    {
        //do something to be mocked
        return somethingToBeMocked;
    }
}

So you need the unit test to mock out getAString . How do you do this?

I have tried just mocking getAString and hoping the test uses the mocked value, but that doesn't work.

I have tried mocking Class1 and setting the unit test class1 to be the mocked object, but I could not figure out how to make the mocked getAString passed into the mocked class1 .

I cannot figure out what to do.

You can't just take any code and unit test it. Code should be testable. What is testable code? It's a code which depends on abstractions instead of implementations. Only way to avoid depending on implementations is providing them via dependency injection:

public class Class1()
{
    private IOtherClass _otherClass; // depend on this abstraction

    public Class1(IOtherClass otherClass) // constructor injection
    {
        _otherClass = otherClass;
    }

    public string getSomeString(string input)
    {
        //dosomething
        return _otherClass.getData(); // you don't know implementation
    }
}

Where IOtherClass interface is implemented by OtherClass

public interface IOtherClass
{
     string getData();
}

Now your class depends on abstraction and you can mock abstraction for tests:

string data = "Foo";
Mock<IOtherClass> otherClassMock = new Mock<IOtherClass>();
otherClassMock.Setup(oc => oc.getData()).Returns(data);
var class1 = new Class1(otherClassMock.Object);
// Act
string result = class1.getSomeString("Bar");
// Assert
Assert.That(result, Is.EqualTo(data));
otherClassMock.VerifyAll(); // check dependency was called

The way you typically accomplish this is by coding to an interface and then injecting an implementation into the class you're trying to test.

In this case, your public API to OtherClass looks like it's really just one method: getData() . So, with that in mind:

public class Class1
{

    private IOtherClass otherClass;
    public Class1(IOtherClass otherClass) 
    {
        this.otherClass = otherClass;
    }

    public string getSomeString(string input)
    {
        return otherClass.getData();
    }
}

public interface IOtherClass 
{
    string getData();
}

public class OtherClass : IOtherClass
{

    public Otherclass() {/*some data*/}    

    public string getData()
    {
        //do something

        string aString = getAString(Input);

        //do something
    }

    private string getAString(string input);
    {
        //do something to be mocked
        return somethingToBeMocked;
    }
}

Then, when you wanted to mock, you create a fake implementation of IOtherClass and provide it to Class1 .

I haven't used Moq for a while, but you should be able to do something like this in your test:

[TestMethod]
public void Foo() 
{
    //Arrange
    var expected = "expectedResult";
    var mock = new Mock<IOtherClass>();
    var otherClass = mock.Setup(foo => foo.getData()).Returns("someValue");
    var myClass = new Class1(otherClass.Object);
    //Act
    var actual = myClass.getSomeString("something");
    //Assert
    Assert.AreEqual(expected, actual);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM