0

I have this controller:

[HttpPost]
        public  ActionResult Create(Company company)
        {

            // try to save the record
            if (ModelState.IsValid)
            {

                // create the command
                var command = new CreateOrUpdateCompanyCommand
                {
                    CompanyId = company.CompanyId,
                    Code = company.Code,
                    Name = company.Name
                };

                // check for errors
                IEnumerable<ValidationResult> errors = _commandBus.Validate(command);

                ModelState.AddModelErrors(errors);

                if (ModelState.IsValid)
                {
                    var result = _commandBus.Submit(command);
                    if (result.Success) 
                        return RedirectToAction("Index");
                }

            }

            // if fail
            return View("Create", company);

        }

I have this test for NUnit:

[Test]
        public void Create()
        {

            const string expectedRouteName = "Index";

            // Mock the arguments
            var mockRepository = Substitute.For<ICompanyRepository>();
            var mockProcessor = Substitute.For<ICommandBus>();

            // Arrange
            var controller = new CompanyController(mockProcessor, mockRepository);

            // Act
            var company = new Company
            {
                Code = "XXXXXXX",
                CompanyId = 1,
                Name = "Sample company"
            };

            var result = controller.Create(company) as RedirectToRouteResult;

            // Assert
            Assert.IsNotNull(result, "Should return a ViewResult");
            Assert.AreEqual(expectedRouteName, result.RouteValues["action"], 
                "View name should have been '{0}'", expectedRouteName);

        }

This is the Model:

public class Company {

[Key]
public int CompanyId { get; set; }

[Required(ErrorMessage = "* (xxxx)")]
[MaxLength(7)]
[RegularExpression("^([A-Z0-9]{7})$", ErrorMessage = "xxx")]
[Display(Name = "Code")]
public string Code { get; set; }

[Required(ErrorMessage = "*")]
[MaxLength(40)]
[Display(Name = "Name")]
public string Name { get; set; }

}

When I Run the test, this function always return false: var result = _commandBus.Submit(command); and the test fails.

I don't know how to test it? Should I mock the _commandBus and set it to return true? I tried in this way but unsuccessfully:

        var mockCommand = Substitute.For<ICommand>();

        mockProcessor.Submit(mockCommand).Success.Returns(true);

To create this project I have got inspiration from this http://efmvc.codeplex.com/

Any advise to me? Thanks.

4

1 回答 1

2

The command you pass to mockProcessor.Submit(mockCommand).Success.Returns(true) needs to be the same one that the code-under-test passes. As the method news up its own command this will never be the case.

Easiest fix is to match any command when you set up your substitute:

var result = CreateSuccessfulResult(); // <-- fill this in as appropriate
mockProcessor.Submit(null).ReturnsForAnyArgs(result);

Setting the Success field on result inline as per your original test should work too I think, but I find it a bit clearer to specify the result required.

You can improve this a bit by matching the expected command type:

mockProcessor.Submit(Arg.Any<CreateOrUpdateCompanyCommand>()).Returns(result);

You can also inspect the command passed if you'd like to test that:

mockProcessor
    .Submit(Arg.Is<CreateOrUpdateCompanyCommand>(x => x.CompanyId = ...))
    .Returns(result);

A similar approach can be used to check the Validate call.

There's a bit more info in the NSubstitute docs.

于 2012-05-17T01:55:06.730 回答