RJardines
RJardines

Reputation: 860

Moq a method in a parent interface throw Exception

I have the following definition

public interface I1 {
    Task RunAsync();
}

public abstract class A{
    protected I1 iInstance;
    public A(I1 i){ this.iInstance = i; }
}

public interface I2 : I1 {}

public class B : A {
    public B(I2 i2):base(i2){}

    public async Task Method1(){
       await this.iInstance.RunAsync()
    }
}

I'm trying to mock B.Method1 using moq something like this:

 var mockI2 = new Mock<I2>();
 mockI2.Setup(i => i.RunAsync()).Verifyable();

 var binstance = new B(mockI2.Object);
 binstance.Method1();

When it reach the line await this.iInstance.RunAsync() I can see there is a mock object for this.iInstance but the call to RunAsync throws Exception with the message

"Object reference not set to an instance of an object."

Looks like the methods was not really mocked, i fear has something to do with hierarchy. In my frustration I tried to use CallBase = true, to mockI2 don't have to much sense but i tried without change the behavior.

Upvotes: 0

Views: 497

Answers (2)

Matt McKinney
Matt McKinney

Reputation: 81

The issue here is that you haven't set up your interface mock properly. Remember, your RunAsync() method returns a Task, so you need to setup your mock to return a Task. Here's one way to do it:

[TestMethod]
public async Task TestMethod1()
{
    _mockI2.Setup(x => x.RunAsync()).Returns(Task.FromResult(true));

    await _bInstance.Method1();

    _mockI2.Verify(x => x.RunAsync(), Times.Once);           
}

Doing this sets up your mock to return a completed task. Then, when you verify that it's been called, it should work.

Upvotes: 2

Vasyl Senko
Vasyl Senko

Reputation: 1829

Your async method now returns null but should return awaitable result - Task, try configure your async method like this:

var mockI2 = new Mock<I2>();
 mockI2.Setup(i => i.RunAsync).Returns(Task.CompletedTask);

Upvotes: 0

Related Questions