维护 VS Test Project 中单元测试方法之间的上下文

发布于 2024-10-17 02:35:37 字数 342 浏览 6 评论 0原文

我想按顺序运行以下单元测试:

  1. 使用名称、密码等的随机数创建新客户。
  2. 检索刚刚创建的客户并断言其属性包含相同的随机数
  3. 在同一用户上调用 ForgotPassword 函数,使用用户名的相同随机数

正如所见,我需要生成一个随机数一次,并在 3 个测试方法中共享它。
我似乎找不到办法做到这一点。

  • 我想过使用 TestContext 对象,但它是为每个实例创建的。
  • 我尝试使用 ClassInitialize() 方法没有帮助,因为它是静态的,因此其他方法无法访问该数字。

知道如何实现我的目标吗?

I want to run the following unit tests, in order:

  1. Create new customer with a random number for name, password etc.
  2. Retrieve the just created customer and assert that its properties contain the same random number
  3. Call the ForgotPassword function on same user, with the same random number for user name

As seen clearly, I need to generate a random number once, and share it across 3 test methods.
I cannot seem to find a way to do that.

  • I thought of using the TestContext object, but that gets created for each instance.
  • I tried Using the ClassInitialize() method doesn't help, as it is static, and therefore the number is not accessible by other methods.

Any idea how to achieve my goal?

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

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

发布评论

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

评论(4

属性 2024-10-24 02:35:37

您可以将共享数据放入静态变量中吗?

像这样简单的事情:

    private static string testValue = "something";

    [TestMethod]
    public void TestMethod1()
    {
        Assert.AreEqual(testValue, "something");
        testValue = "something2";
    }

    [TestMethod]
    public void TestMethod2()
    {
        Assert.AreEqual(testValue, "something2");
        testValue = "something3";
    }

    [TestMethod]
    public void TestMethod3()
    {
        Assert.AreEqual(testValue, "something3");
    }

更新:总结关于这个问题的其他评论,我认为每个人都完全同意在单元测试之间保持状态是一个坏主意。我的回答只是如果有必要的话,这样做的一种方法。正如我在另一条评论中提到的,我过去必须这样做,但不是为了单元测试。有时,在集成/回归测试之间保持状态是有益的/必要的,因为您不一定想要模拟对象或隔离应用程序的某些部分。作为软件测试人员,您并不总是具有影响力/能力/权限来立即重构或重新构建应用程序以使其最适合此测试。

Can you just place your shared data into static variables?

Something simple like this:

    private static string testValue = "something";

    [TestMethod]
    public void TestMethod1()
    {
        Assert.AreEqual(testValue, "something");
        testValue = "something2";
    }

    [TestMethod]
    public void TestMethod2()
    {
        Assert.AreEqual(testValue, "something2");
        testValue = "something3";
    }

    [TestMethod]
    public void TestMethod3()
    {
        Assert.AreEqual(testValue, "something3");
    }

Update: To summarize other comments on this question, I think that everyone is in complete agreement that keeping state between unit tests is a bad idea. My answer was simply a way to do this, if necessary. As I mentioned in another comment, I have had to do this in the past, but not for unit tests. It is sometimes beneficial/necessary to keep state between integration/regression tests where you don't necessarily want to mock objects or isolate parts of the application. As a software tester, you do not always have the influence/ability/permission to immediately refactor or rearchitect an application to be optimal for this testing.

仙女 2024-10-24 02:35:37

您想要在这里做的是在 IRepository 接口后面使用类似存储库的东西:

interface IRepository{
    Customer GetCustomer(int id);
}

您可以在代码中实现一个真正的类来查询数据库,但在您的测试中您可以“模拟”此接口以准确返回您想要的内容。 Moq 是我的最爱 - 接下来是伪代码,但希望您能得到想法:

[Test]
public void Customer_Should_Have_CreateAt_Set_To_Today{
  var mock = new Mock<IRepository>();
  mock.Setup(x => x.GetCustomer(100)).Returns(new Customer{id = 100, Name = "Steve"});

  var Customer = mock.Object;
  Assert.Equal(Customer.CreatedAt,Date.Today);
}

这里的想法是您完全控制需要控制的数据,而不依赖于对象何时实例化等。

What you want to do here is use something like a Repository behind an IRepository interface:

interface IRepository{
    Customer GetCustomer(int id);
}

You can implement a real class in your code that will query a database, but in your tests you can "Mock" this interface to return exactly what you want. Moq is my favorite - and what follows is pseudo code but hopefully you'll get the idea:

[Test]
public void Customer_Should_Have_CreateAt_Set_To_Today{
  var mock = new Mock<IRepository>();
  mock.Setup(x => x.GetCustomer(100)).Returns(new Customer{id = 100, Name = "Steve"});

  var Customer = mock.Object;
  Assert.Equal(Customer.CreatedAt,Date.Today);
}

The idea here is that you control, completely, the data you need to control without relying on when an object is instantiated etc.

伤感在游骋 2024-10-24 02:35:37

运行共享上下文的单元测试是一个非常糟糕的主意。尽管我愿意接受建议,但我从来没有找到按照你的建议去做的充分理由。

如果有人以不同的顺序或单独运行你的测试,那么他们就会失败。像这样的测试被称为flakey - 有时它们会通过,但另一些则不会 - 并且尚不清楚原因。

最好使用像 Rhino Mocks 这样的模拟框架来实例化模拟依赖项您需要的状态。这样,每个测试都是一个独立的测试,它验证特定的事物,而不参考任何其他测试。

您会发现维护此类测试变得更加容易,并且结果中的误报和误报也会减少。

It is a really bad idea to be running unit tests that share context. Although I am open to suggestions, I've never come across a good reason for doing what you are suggesting.

If somebody runs your tests in a different order, or in isolation, then they will fail. Tests like this are termed flakey - they pass sometimes, but not others - and it isn't clear why.

It's much better to use a mocking framework like Rhino Mocks to instantiate the mock dependencies in the state that you need. That way, each test is a standalone test that verifies a specific thing without reference to any other tests.

You will find it much easier to maintain tests like these, and there'll be fewer false positives and negatives in your results.

痴情 2024-10-24 02:35:37

构建具有依赖关系的单元测试是一种不好的形式。然而,构建带有依赖项的功能测试并不是一种糟糕的形式。事实上,任何具有正常复杂程度的应用程序几乎都需要它。

您想要做的不是单元测试。这是一个功能测试。并且您确实需要在测试方法之间共享值才能从用户的角度完成任务。

It is bad form to build unit tests with dependencies. It is not, however, bad form to build functional tests with dependencies. In fact, it's almost required in any application with a normal level of complexity.

What you're trying to do is not a unit test. It's a functional test. And you do need ot share values between test methods to accomplish things from a user's perspective.

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