简体   繁体   English

使用Rhino模拟的NUnit测试方法不起作用-C#

[英]NUnit Test method with Rhino mocks does not work - C#

I have created a web api project and implemented the below HTTP POST method in AccountController and the related service method & repository method in AccountService & AccountRepository respectively. 我创建了一个Web api项目,并分别在AccountController中实现了以下HTTP POST方法,在AccountService和AccountRepository中分别实现了相关的服务方法和存储库方法。

// WEB API 
public class AccountController : ApiController
{
    private readonly IAccountService _accountService;
    public AccountController()
    {
        _accountService = new AccountService();
    }

    [HttpPost, ActionName("updateProfile")]
    public IHttpActionResult updateProfile([FromBody]RequestDataModel request)
    {
        var response = _accountService.UpdateProfile(request.UserId, request.Salary);
        return Json(response);
    }
}


public class RequestDataModel
{
    public int UserId { get; set; }
    public decimal Salary { get; set; }
}

// Service / Business Layer

public interface IAccountService
{
    int UpdateProfile(int userId, decimal salary);
}

public class AccountService : IAccountService
{
    readonly IAccountRepository _accountRepository = new AccountRepository();

    public int UpdateProfile(int userId, decimal salary)
    {
        return _accountRepository.UpdateProfile(userId, salary);
    }
}


// Repository / Data Access Layer

public interface IAccountRepository
{
    int UpdateProfile(int userId, decimal salary);
}

public class AccountRepository : IAccountRepository
{
    public int UpdateProfile(int userId, decimal salary)
    {
        using (var db = new AccountEntities())
        {
            var account = (from b in db.UserAccounts where b.UserID == userId select b).FirstOrDefault();
            if (account != null)
            {
                account.Salary = account.Salary + salary;
                db.SaveChanges();
                return account.Salary;
            }
        }
        return 0;
    }
}

Also, I wanted to implement a NUNIT test case. 另外,我想实现一个NUNIT测试用例。 Here is the code. 这是代码。

public class TestMethods
{
    private IAccountService _accountService;
    private MockRepository _mockRepository;

    [SetUp]
    public void initialize()
    {
        _mockRepository = new MockRepository();

    }

    [Test]
    public void TestMyMethod()
    {
        var service = _mockRepository.DynamicMock<IAccountService>();

        using (_mockRepository.Playback())
        {
            var updatedSalary = service.UpdateProfile(123, 1000);
            Assert.AreEqual(1000, updatedSalary);
        } 
    }
}

Note that I have used Rhino mocks library to implement the mock repository. 请注意,我已经使用Rhino模拟库来实现模拟存储库。

The issue is this does not return the expected output. 问题是这不会返回预期的输出。 Looks like it does not trigger the UpdateProfile() method in my service class. 看起来它不会触发我的服务类中的UpdateProfile()方法。 it returns NULL. 它返回NULL。

All of these classes are tightly coupled to implementation concerns and should be refactored to be decoupled and dependent on abstractions. 所有这些类都与实现问题紧密耦合,应重构为解耦并依赖抽象。

public class AccountController : ApiController  {
    private readonly IAccountService accountService;

    public AccountController(IAccountService accountService) {
        this.accountService = accountService;
    }

    [HttpPost, ActionName("updateProfile")]
    public IHttpActionResult updateProfile([FromBody]RequestDataModel request) {
        var response = accountService.UpdateProfile(request.UserId, request.Salary);
        return Ok(response);
    }
}

public class AccountService : IAccountService {
    private readonly IAccountRepository accountRepository;

    public AccountService(IAccountRepository accountRepository) {
        this.accountRepository = accountRepository;
    }

    public int UpdateProfile(int userId, decimal salary) {
        return accountRepository.UpdateProfile(userId, salary);
    }
}

Now for unit testing in isolation the abstract dependencies can be mocked and injected into the subject under test. 现在,对于隔离的单元测试,可以模拟抽象依赖关系并将其注入到测试对象中。

For example the following tests the AccountService.UpdateProfile by mocking a IAccountRepository and injecting it into the AccountService . 例如,以下通过IAccountRepository并将其注入AccountService.UpdateProfile来测试AccountService

public class AccountServiceTests {

    [Test]
    public void UpdateProfile_Should_Return_Salary() {
        //Arrange
        var accountRepository = MockRepository.GenerateMock<IAccountRepository>(); 
        var service = new AccountService(accountRepository);

        var userId = 123;
        decimal salary = 1000M;
        var expected = 1000;

        accountRepository.Expect(_ => _.UpdateProfile(userId, salary)).Return(expected);

        //Act
        var updatedSalary = service.UpdateProfile(userId, salary);

        //Assert
        Assert.AreEqual(expected, updatedSalary);
    }
}

The same approach can be taken for testing the AccountController . 可以采用相同的方法来测试AccountController Instead you would mock the IAccountService and inject that into the controller to test the action and assert the expected behavior. 相反,您可以模拟IAccountService并将其注入到控制器中以测试操作并声明预期的行为。

Make sure to register the abstractions and their implementations with the DI container in the composition root of the application. 确保在应用程序的组合根目录中的DI容器中注册抽象及其实现。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM