Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mocked Object Still Making Calls to Service

So I'm writing tests for our MVC4 application and I'm testing Controller actions specifically. As I mention in the title, the test still hits the service (WCF) instead of returning test data. I have this controller:

public class FormController : Controller
{
    public SurveyServiceClient Service { get; set; }
    public SurveyDao Dao { get; set; }

    public FormController(SurveyServiceClient service = null, SurveyDao dao = null)
    {
        this.Service = service ?? new SurveyServiceClient();
        this.Dao = dao ?? new SurveyDao(Service);
    }

    //
    // GET: /Form/

    public ActionResult Index()
    {
        var formsList = new List<FormDataTransformContainer>();
        Dao.GetForms().ForEach(form => formsList.Add(form.ToContainer()));

        var model = new IndexViewModel(){forms = formsList};
        return View("Index", model);
    }

And it uses this DAO object:

public class SurveyDao
{
    private readonly SurveyServiceClient _service;
    private readonly string _authKey;

    public SurveyDao(SurveyServiceClient serviceClient)
    {
        _service = serviceClient;
    }

    ....

    public FormContract[] GetForms()
    {
        var forms = _service.RetrieveAllForms();
        return forms;
    }

And this is my test using JustMock, the mock on GetForms() returns some test data in a helper class:

[TestClass]
public class FormControllerTest
{
    private SurveyDao mockDao;
    private SurveyServiceClient mockClient;

    public FormControllerTest()
    {
        mockClient = Mock.Create<SurveyServiceClient>();
        mockDao = Mock.Create<SurveyDao>(mockClient);
    }

    [TestMethod]
    public void TestIndexAction() 
    {
        //Arrange
        var controller = new FormController(mockClient, mockDao);
        Mock.Arrange(() => mockDao.GetForms()).Returns(TestHelpers.FormContractArrayHelper);

        //Act
        var result = controller.Index() as ViewResult;

        //Assert
        Assert.IsInstanceOfType(result.Model, typeof(IndexViewModel));
    }
}

My problem is that when I run the test, the Service is still being called. I've verified this using Fiddler as well as debugging the test and inspecting the value of "result" which is populated with our service's test data.

EDIT:

I've changed the test constructor to be a [TestInitialize] function, so the Test now looks like this:

[TestClass]
public class FormControllerTest
{
    private SurveyDao mockDao;
    private SurveyServiceClient mockClient;

    [TestInitialize]
    public void Initialize()
    {
        mockClient = Mock.Create<SurveyServiceClient>();
        mockDao = Mock.Create<SurveyDao>(Behavior.Strict);
    }

    [TestMethod]
    public void TestIndexAction() 
    {
        //Arrange
        var controller = new FormController(mockClient, mockDao);
        Mock.Arrange(() => mockDao.GetForms()).Returns(TestHelpers.FormContractArrayHelper);

        //Act
        var result = controller.Index() as ViewResult;

        //Assert
        Assert.IsInstanceOfType(result.Model, typeof(IndexViewModel));
    }
}
like image 430
mmcclannahan Avatar asked Oct 03 '22 17:10

mmcclannahan


2 Answers

Please verify that you are using the correct assembly for JustMock. There are a few different ones (VisualBasic, Silverlight, JustMock). The JustMock one is the one you should be including in your project.

Failure to include the correct one will cause the behavior that you are describing (method not being properly stubbed).

like image 83
Trey George Avatar answered Oct 13 '22 11:10

Trey George


The JustMock manual explains (highlights by me):

By default Telerik JustMock uses loose mocks and allows you to call any method on a given type. No matter whether the method call is arranged or not you are able to call it.

You can control this behavior when calling the Create() method of you Mock:

var foo = Mock.Create<IFoo>(Behavior.Strict);

There you can specify what the mock object should do if you have not explicitly implemented a certain method. In your case (I think it is the default behavior) the mock indeed calls the original method on the object that you want to mock.

You have the following choices in the Behavior Enumeration enumeration:

  • Loose: Specifies that by default mock calls will behave like a stub, unless explicitly setup.
  • RecursiveLoose: Specifies that by default mock calls will return mock objects, unless explicitly setup.
  • Strict: Specifies that any calls made on the mock will throw an exception if not explictly set.
  • CallOriginal: Specifies that by default all calls made on mock will invoke its corresponding original member unless some expecations are set.
like image 41
Jens H Avatar answered Oct 13 '22 11:10

Jens H