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

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

我创建了一个 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;
    }
}

另外,我想实现一个 NUNIT 测试用例。这是代码。

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);
        } 
    }
}

请注意,我使用 Rhino 模拟库来实现模拟存储库。

问题是这不是 return 预期的输出。看起来它不会触发我的服务 class 中的 UpdateProfile() 方法。它 return 为 NULL。

所有这些 类 都与实现问题紧密耦合,应该重构以解耦并依赖于抽象。

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);
    }
}

现在,对于独立的单元测试,可以模拟抽象依赖项并将其注入到被测对象中。

例如,下面通过模拟 IAccountRepository 并将其注入 AccountService.

来测试 AccountService.UpdateProfile
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);
    }
}

可以采用相同的方法来测试 AccountController。相反,您将模拟 IAccountService 并将其注入控制器以测试操作并断言预期的行为。

确保在应用程序的组合根中向 DI 容器注册抽象及其实现。