我如何在Web API的.NET中编写单元测试

发布于 2025-01-24 06:29:25 字数 2642 浏览 1 评论 0原文

我的删除方法控制器:

[HttpDelete("{toDoListId}")]
    public async Task<ActionResult> DeleteToDoList(int toDoListId)
    {

        var toDoListEntity = await _toDoListRepository.GetSpecificTodoAsync(toDoListId);
            
        if (toDoListEntity == null)
        {
            return NotFound();
        }
        _toDoListRepository.DeleteToDoList(toDoListEntity); 
        
        await _toDoListRepository.SaveChangesAsync();
        return NoContent();

    }

我的存储库:

public async Task<ToDoList?> GetSpecificTodoAsync(int taskId)
    {
        return await _context.ToDoLists.Where(c => c.Id == taskId).FirstOrDefaultAsync();
    }

public void DeleteToDoList(ToDoList toDoListDto)
    {
        _context.ToDoLists.Remove(toDoListDto);
    }

我的测试柜检查项目是否已删除,并且在删除后是否返回任何内容。但是我的两个测试用例都失败了。关于如何为删除部分编写测试用例的任何帮助,我真的很感激。我也在尝试测试其他方法,但不幸的是,我被困在这里。请帮助我

public class UnitTest1
    {
 
        private readonly Mock<IToDoListRepository> repositoryStub = new ();
        private readonly Mock<IMapper> mapper = new Mock<IMapper>();
        private readonly Random Rand = new();
        private ToDoList GenerateRandomItem()
        {
            return new()
            {
                Id = Rand.Next(),
                Description= Guid.NewGuid().ToString(),
                Title = Guid.NewGuid().ToString(),
                StartDate = DateTime.Now,
                EndDate = DateTime.Now,
                Done = false
            };
        }

 [Fact]
        public void Delete_removesEntry()
        {
            //arrange
            var existingItem =  GenerateRandomItem();
            
            var controller = new ToDoController(repositoryStub.Object, mapper.Object);
            var itemID = existingItem.Id;

            //act
            controller.DeleteToDoList(itemID);

            //assert
            
            Assert.Null(repositoryStub.Object.GetSpecificTodoAsync(itemID));

        }
        [Fact]
        public async Task DeleteItemAsync_WithExistingItem_ReturnNoContent()
        {
            //Arrange
            var existingItem = GenerateRandomItem();
            repositoryStub.Setup(repo => repo.GetSpecificTodoAsync(existingItem.Id)).ReturnsAsync((existingItem));

            var itemID = existingItem.Id;
            var controller = new ToDoController(repositoryStub.Object, mapper.Object);
            //Act

            var result = await controller.DeleteToDoList(itemID);

            //assert
            result.Should().BeOfType<NoContentResult>();

        }

My controller for the delete method :

[HttpDelete("{toDoListId}")]
    public async Task<ActionResult> DeleteToDoList(int toDoListId)
    {

        var toDoListEntity = await _toDoListRepository.GetSpecificTodoAsync(toDoListId);
            
        if (toDoListEntity == null)
        {
            return NotFound();
        }
        _toDoListRepository.DeleteToDoList(toDoListEntity); 
        
        await _toDoListRepository.SaveChangesAsync();
        return NoContent();

    }

My repository :

public async Task<ToDoList?> GetSpecificTodoAsync(int taskId)
    {
        return await _context.ToDoLists.Where(c => c.Id == taskId).FirstOrDefaultAsync();
    }

public void DeleteToDoList(ToDoList toDoListDto)
    {
        _context.ToDoLists.Remove(toDoListDto);
    }

My testcase for checking if the item got deleted and if it returns no content after being deleted. But both of my test cases are failing. Any help on how to write test cases for the delete part, I would be really grateful. I am also trying to test other methods but I am unfortunately stuck here. Please kindly help me

public class UnitTest1
    {
 
        private readonly Mock<IToDoListRepository> repositoryStub = new ();
        private readonly Mock<IMapper> mapper = new Mock<IMapper>();
        private readonly Random Rand = new();
        private ToDoList GenerateRandomItem()
        {
            return new()
            {
                Id = Rand.Next(),
                Description= Guid.NewGuid().ToString(),
                Title = Guid.NewGuid().ToString(),
                StartDate = DateTime.Now,
                EndDate = DateTime.Now,
                Done = false
            };
        }

 [Fact]
        public void Delete_removesEntry()
        {
            //arrange
            var existingItem =  GenerateRandomItem();
            
            var controller = new ToDoController(repositoryStub.Object, mapper.Object);
            var itemID = existingItem.Id;

            //act
            controller.DeleteToDoList(itemID);

            //assert
            
            Assert.Null(repositoryStub.Object.GetSpecificTodoAsync(itemID));

        }
        [Fact]
        public async Task DeleteItemAsync_WithExistingItem_ReturnNoContent()
        {
            //Arrange
            var existingItem = GenerateRandomItem();
            repositoryStub.Setup(repo => repo.GetSpecificTodoAsync(existingItem.Id)).ReturnsAsync((existingItem));

            var itemID = existingItem.Id;
            var controller = new ToDoController(repositoryStub.Object, mapper.Object);
            //Act

            var result = await controller.DeleteToDoList(itemID);

            //assert
            result.Should().BeOfType<NoContentResult>();

        }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

记忆里有你的影子 2025-01-31 06:29:25

两种测试用例都失败了,因为尚未设置模拟的行为,以表现为每个测试用例的预期。

由于它们共享相同的模拟实例,因此在显示的测试中也有潜在的种族条件。这将在设置模拟时会导致问题,因为一个测试案例可能会覆盖另一个案例的设置。

更新测试,以使它们彼此隔离。

在第一个测试中,可以通过检查模拟查看是否调用预期成员来验证预期行为。

[Fact]
public async Task DeleteToDoList_Should_RemoveEntry() {
    //arrange
    ToDoList existingItem =  GenerateRandomItem();
    var itemID = existingItem.Id;
    
    Mock<IToDoListRepository> repositoryStub = new ();
    
    //Setup expected behavior of mock
    repositoryStub
        .Setup(_ => _.GetSpecificTodoAsync(itemID))
        .ReturnsAsync(existingItem);
    
    var controller = new ToDoController(repositoryStub.Object, mapper.Object);

    //act
    await controller.DeleteToDoList(itemID);

    //assert
    repositoryStub.Verify(_ => _.DeleteToDoList(existingItem));
}

在另一个测试中,设置模拟需要,以确保主题执行完成。

[Fact]
public async Task DeleteToDoList_WithExistingItem_Should_ReturnNoContent() {
    //Arrange
    ToDoList existingItem =  GenerateRandomItem();
    var itemID = existingItem.Id;
    
    Mock<IToDoListRepository> repositoryStub = new ();
    
    //Setup expected behavior of mock
    repositoryStub
        .Setup(_ => _.GetSpecificTodoAsync(itemID))
        .ReturnsAsync(existingItem);
    repositoryStub.Setup(_ => _.SaveChangesAsync()).ReturnsAsynt(true);
    
    var controller = new ToDoController(repositoryStub.Object, mapper.Object);
    
    //Act
    ActionResult result = await controller.DeleteToDoList(itemID);

    //assert
    result.Should().BeOfType<NoContentResult>();
}

Both test cases are failing because the mock has not been setup to behave as expected for each test case.

There is also a potential race condition in the shown tests since they are sharing the same mock instance. This will cause issues when setting up the mock as one test case could potentially override the setup of another case.

Update the tests so that they are isolated from each other.

In the first test, the expected behavior can be verified by checking the mock to see if the expected member was invoked.

[Fact]
public async Task DeleteToDoList_Should_RemoveEntry() {
    //arrange
    ToDoList existingItem =  GenerateRandomItem();
    var itemID = existingItem.Id;
    
    Mock<IToDoListRepository> repositoryStub = new ();
    
    //Setup expected behavior of mock
    repositoryStub
        .Setup(_ => _.GetSpecificTodoAsync(itemID))
        .ReturnsAsync(existingItem);
    
    var controller = new ToDoController(repositoryStub.Object, mapper.Object);

    //act
    await controller.DeleteToDoList(itemID);

    //assert
    repositoryStub.Verify(_ => _.DeleteToDoList(existingItem));
}

In the other test, the mock needs be setup to make sure the subject executes to completion.

[Fact]
public async Task DeleteToDoList_WithExistingItem_Should_ReturnNoContent() {
    //Arrange
    ToDoList existingItem =  GenerateRandomItem();
    var itemID = existingItem.Id;
    
    Mock<IToDoListRepository> repositoryStub = new ();
    
    //Setup expected behavior of mock
    repositoryStub
        .Setup(_ => _.GetSpecificTodoAsync(itemID))
        .ReturnsAsync(existingItem);
    repositoryStub.Setup(_ => _.SaveChangesAsync()).ReturnsAsynt(true);
    
    var controller = new ToDoController(repositoryStub.Object, mapper.Object);
    
    //Act
    ActionResult result = await controller.DeleteToDoList(itemID);

    //assert
    result.Should().BeOfType<NoContentResult>();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文