0

我在页面后面的 asp.net 代码中有以下方法,它调用存储过程并返回结果。我不确定我应该为测试该方法而编写的单元测试方法的定义。

public List<BlogDetail> GetData()
    {
        List<BlogDetail> allBlogDetail = new List<BlogDetail>();

        using (var db = new BloggingContext("CodeFirstSampleConnectionString")) //name=CodeFirstSample
        {
            allBlogDetail = db.Database.SqlQuery<BlogDetail>("uspGetAllBlogs").ToList();
        }

        return allBlogDetail;
    }

以下是我为测试此方法而编写的单元测试方法。据我所知,在单元测试中进行数据库调用不是一个好习惯,我在单元测试方法中进行数据库调用违反了这一点。

public void GetDataTest()
    {
        Default target = new Default();
        List<BlogDetail> expected = new List<BlogDetail>();
        List<BlogDetail> actual = new List<BlogDetail>();

        using (var db = new BloggingContext("DemoConnectionString")) 
        {
            expected = db.Database.SqlQuery<BlogDetail>("uspGetAllBlogs").ToList();
        }

        actual = target.GetData();

        Assert.AreEqual(expected.Count, actual.Count);

        for (int i = 0; i < expected.Count; i++)
        {
            Assert.AreEqual(expected[i].BlogID, actual[i].BlogID);
            Assert.AreEqual(expected[i].BlogName, actual[i].BlogName);
            Assert.AreEqual(expected[i].PostID, actual[i].PostID);
            Assert.AreEqual(expected[i].PostTitle, actual[i].PostTitle);
            Assert.AreEqual(expected[i].PostContent, actual[i].PostContent);
        }
    }

我已经读过单元测试应该是可重复和可预测的,并且通过编写上述方法,我违反了这两个规则。

此单元测试在本地数据库中运行至少需要 30 秒,显然在使用远程数据库进行测试时需要更多时间。

存储过程的结果也是不可预测的,因为存储过程在不同时间调用时可以返回变量记录。由于数据库定期提供数据。

我不知道单元测试方法的定义。我的单元测试方法正确吗?我需要采取不同的方法吗?请帮忙。

4

2 回答 2

2

您想测试该GetData()方法是否调用了uspGetAllBlogsSP。在您当前的代码中,这是不可能的,因为该GetData()方法做得太多。

当存储库被注入到您的Default

interface IBlogRepository
{
    List<BlogDetail> GetAllBlogs();
}

class BlogRepository : IBlogRepository
{
    public List<BlogDetail> GetAllBlogs()
    {
        using (var db = new BloggingContext("CodeFirstSampleConnectionString"))
        {
            return db.Database.SqlQuery<BlogDetail>("uspGetAllBlogs").ToList();
        }
    }
}

class Default
{
    private readonly IBlogRepository _blogRepository;

    public Default(IBlogRepository blogRepository)
    {
        _blogRepository = blogRepository;
    }

    public List<BlogDetail> GetData()
    {
        return _blogRepository.GetAllBlogs();
    }
}

现在您可以在测试时模拟您的存储库,并且您只需验证是否调用存储库的GetAllBlogs()方法,而不是它返回的内容:

public void GetDataTest()
{
    var mockRepository = new Mock<IBlogRepository>();
    mockRepository.Setup(r => r.GetAllBlogs()).Returns(new List<BlogDetail>());
    Default target = new Default(mockRepository.Object);

    var actual = target.GetData();

    Assert.AreEqual(0, actual.Count);       
    mockRepository.Verify(r => r.GetAllBlogs(), Times.Once());
}

在此之后,您将想要对您的BlogRepository. 为了做到这一点,您必须连接您的接口BloggingContext并验证Database.SqlQuery()使用正确的参数调用该方法,依此类推。

于 2013-10-03T11:43:37.957 回答
0

这个问题的答案会很长...尝试阅读有关分离 UI(asp.net 页面及其背后的代码)和应用程序逻辑的内容。也许可以看看依赖注入。您只需要做的就是将Repository模式或类似的东西注入您的类并使其获取数据。这样,您可以注入将返回预定义数据的存储库对象的模型实现。

于 2013-10-03T11:41:46.127 回答