views:

176

answers:

1

Hi,

I have the following test using NMock which fails. It used to work when the result from the service call was passed to the view but it now fails since the results are converted to dto's.

I think this might mean I need to create a custom matcher but I am not sure. Does anyone have any ideas?

Error Message:

Test method Dgc.Cpo.RM.UI.Presentation.Test.ProjectPresenterTest.LoadProjectsTest threw exception:  NMock2.Internal.ExpectationException: unexpected invocation of projectView.SetProjects(<System.Collections.Generic.List`1[Dgc.Cpo.ResourceManagement.UI.Presentation.ProjectPresentationDto]>)

Expected: 1 time: projectView.SetProjects(equal to ) [called 0 times] .

Code:

public void LoadProjectsTest()
    {
        IList<ProjectServiceGetProjectsResponse> expectedGetProjectsResponse = new List<ProjectServiceGetProjectsResponse>();
        expectedGetProjectsResponse.Add(new ProjectServiceGetProjectsResponse() { Id = 1, Name = "Project 1", RefNo = "001", Complete = false, Dropped = false });
        expectedGetProjectsResponse.Add(new ProjectServiceGetProjectsResponse() { Id = 2, Name = "Project 2", RefNo = "002", Complete = true, Dropped = false });
        expectedGetProjectsResponse.Add(new ProjectServiceGetProjectsResponse() { Id = 3, Name = "Project 3", RefNo = "003", Complete = false, Dropped = true });

        IList<ProjectPresentationDto> expectedSetProjectsRequest = new List<ProjectPresentationDto>();
        expectedSetProjectsRequest.Add(new ProjectPresentationDto(expectedGetProjectsResponse[0]));
        expectedSetProjectsRequest.Add(new ProjectPresentationDto(expectedGetProjectsResponse[1]));
        expectedSetProjectsRequest.Add(new ProjectPresentationDto(expectedGetProjectsResponse[2]));

        ProjectPresenter_Accessor target = new ProjectPresenter_Accessor(this.mockView,
                                                                         this.mockProjectService);

        Expect.Once.On(this.mockProjectService).Method("GetProjects").Will(Return.Value(expectedGetProjectsResponse));
        Expect.Once.On(this.mockView).Method("SetProjects").With(expectedSetProjectsRequest);

        target.LoadProjects();

        this.mock.VerifyAllExpectationsHaveBeenMet();

    }
A: 

You've got it - you need to create a custom matcher and a static factory class, as described in the "Customer Matchers in NMock 2.0" section of the NMock 2.0 advanced topics documentation.

By default, NMock uses Equals to match arguments passed to expectations (in your case, to see whether LoadProjects sets mockView.Projects to expectedSetProjectsRequest or not).

The List<T>.Equals implementation (inherited from Object) just checks whether the two variables reference the same object, and in this case they clearly do not. (It looks like the LoadProjects method creating a new DTO list instance in the process of transforming the get accessor results into DTOs.)

You have to tell NMock what to do instead of checking reference equality. Luckily the custom ListMatcher (and corresponding IsList class) from the NMock documentation I linked above may do the trick all by itself. If ProjectPresentationDto.Equals checks for value equality, you can use that example class as-is. If not, you'll have to customize it to define equality for your DTOs.

Jeff Sternal
Thanks that worked a treat.James :-)
m0gb0y74