0

I need to mock with NSubstitute and need to set local variable command of a class LoanCreateHandler to mock data with it's parameter Z. I have code like give below:

public class ClassA {
  public string Prop1 { get; set; } 
  public string Prop2 { get; set; } 
  … // Here I have some other properties
}

public class CreateLoanCommand {
  public string X { get; set; } 
  public string Y { get; set; } 
  public ClassA Z { get; set; } 
}    

public class LoanCreateHandler {       

    public Response Handle(LoanCreateRequest request)
    {
        var response = CreateTypedResponse();
        var command = new CreateLoanCommand
        { 
            X = request.X,
            Y = request.Y
        };

        _cqsCommandProcessor.Execute(command); //here I am setting value of command.Z param

        if (command.Z == null)
        {
          //do something
        }else{
          //do another
        }

        return true; // returns response 
    }
}

So here when I want to mock LoanCreateHandler for code coverage. Else loop code is not getting covered. Please find unit test below:

[TestClass]
public class LoanCreateHandlerTests
{
    [TestMethod, TestCategory(Tc.Unit)]
    public void LoanCreateHandler_SuccessTest()
    {
        var loanCreateRequest = new LoanCreateRequest
        { 
            X = "val1",
            Y = "val2"                                    
        };
        var loanCreateResponse = true;


        var createLoanCommand = new CreateLoanCommand()
        {
            X = "val1",
            Y = "val2",
            Z = new ClassA()
            {
                Prop1 = "val1", Prop2 = "val2"…
            }
        };

        _TestHelper.CqsCommandProcessor.Execute(Arg.Any<CreateLoanCommand>());

        var loanCreateHandler = new LoanCreateHandler();
        loanCreateHandler.Handle(loanCreateRequest).Returns(loanCreateResponse);
        //here when call goes to Handle() method it creates new LoanCreateRequest object and I want to replace that object with my LoanCreateRequest object, which is created above.

        Assert.IsNotNull(loanCreateResponse);            
    }
}
Marcio Rinaldi
  • 3,305
  • 24
  • 23
Rohit Sonaje
  • 522
  • 4
  • 14
  • Can you please clarify which class you are mocking? Please note that you cannot use `Returns` with objects that were not created with `Substitute.For`, nor with non-virtual members (interfaces members work fine, as do classes with members marked `virtual`). As an aside, the test in the question is not checking `LoanCreateHandler` -- it is checking if a boolean variable created during the test (`loanCreateResponse`) is not null. – David Tchepak Feb 01 '16 at 22:28

1 Answers1

1

You should use the When..Do callback to setup void method.

I'm assuming _TestHelper.CqsCommandProcessor returns the same object that LoanCreateHandler._cqsCommandProcessor does.

That said, you should do something like this:

[TestClass]
public class LoanCreateHandlerTests
{
    [TestMethod, TestCategory(Tc.Unit)]
    public void LoanCreateHandler_SuccessTest()
    {
        var z = new ClassA()
        {
            Prop1 = "val1",
            Prop2 = "val2"
        };

        _TestHelper.CqsCommandProcessor
            .When(x => x.Execute(Arg.Any<LoanCreateRequest>()))
            .Do(x => x.Arg<LoanCreateRequest>().Z = z);

        var loanCreateHandler = new LoanCreateHandler();
        var loanCreateRequest = new LoanCreateRequest
        {
            X = "val1",
            Y = "val2"
        };
        var loanCreateResponse = loanCreateHandler.Handle(loanCreateRequest);

        Assert.IsNotNull(loanCreateResponse);
    }
}
Marcio Rinaldi
  • 3,305
  • 24
  • 23
  • I think this is a good answer. It may also be worth adding to the assumptions that `_TestHelper.CqsCommandProcessor` must be created with `Substitute.For` (or similar, providing the type is an interface or a class where `Execute` is virtual)? – David Tchepak Feb 01 '16 at 22:30
  • @Marcio Thanks buddy. When()...Do()... worked for me. I got the logic to set local variable value under LoanCreateHandler. – Rohit Sonaje Feb 02 '16 at 05:20