【问题标题】:How do I use a global variable in unit testing?如何在单元测试中使用全局变量?
【发布时间】:2015-03-18 16:04:17
【问题描述】:

我也需要一个在其他测试的第一个测试中初始化的对象。 为了防止代码重复,我想将我在第一个测试中创建的对象保存在一个全局变量中。这就是我所做的:

namespace Project.WebUIV2.Tests {
    [TestClass]
    public class FilmSelectieControllerTests {
        private FilmSelectieController controller;
        [TestMethod]
        public void CanInitializeController() {
            Mock<IRepository<Voorstelling>> mockIRepository1 = new Mock<IRepository<Voorstelling>>();
            Mock<IRepository<Film>> mockIRepository2 = new Mock<IRepository<Film>>();
            Mock<IRepository<Zaal>> mockIRepository3 = new Mock<IRepository<Zaal>>();
            Film film = new Film { titel = "Film" };
            mockIRepository2.Setup(m => m.Add(film));
            var repository1 = mockIRepository1.Object;
            var repository2 = mockIRepository2.Object;
            var repository3 = mockIRepository3.Object;
            var controller = new FilmSelectieController(repository1, repository2, repository3);
            Assert.IsNotNull(controller);
            Assert.IsInstanceOfType(controller, typeof(FilmSelectieController));
            this.controller = controller;

        }

        [TestMethod]
        public void IsCreated() {
            Assert.IsInstanceOfType(controller, typeof(FilmSelectieController));
        }
    }
}

Testmethod CanInitializeController() 成功,而 isCreated() 失败。

在第一个测试中,我创建了 FilmSelectieController 对象。

如何在接下来的测试中使用该对象?

感谢安东尼·佩格拉姆

解决办法:

..*/
private Controller controller;

[TestInitialize]
public void Initialize() {
    var parameter = /*...test data that i need in all tests...*/
    this.controller = new Controller(parameter)
}

[TestMethod]
public void test1 {
    result = controller.FirstMethod();
    //assert something
}

[TestMethod]
public void test2 {
    result = controller.SecondMethod();
    //assert something
}
/*..

【问题讨论】:

  • 您应该在每次设置例程中重新创建它。
  • 一开始我就是这么做的,然后我认为那是代码重复,我认为有办法防止这种情况发生。
  • 写一个新方法。在单元测试中重复对我来说很好。
  • 如果您发现自己重复了大量代码,请尝试将其抽象为清楚表达意图的类/方法。复制本身在单元测试中并不好,如果您的代码发生更改,您不想使用几乎相同的 sn-p 更新 600 个单元测试。投资于您的测试项目设计和架构,它本质上是您的生产代码的一部分,如果不是更重要的话。
  • 哈哈我遇到了你的问题,我们正在做完全相同的项目! (也在 Avans Hogeschool)

标签: c# unit-testing model-view-controller


【解决方案1】:

您混合了几件事,所以让我指出这种方法的一些问题。

隔离

一个好的单元测试是一种在速度、重复性等其他几个方面是独立的测试。这意味着其他测试的结果或顺序不应影响其他测试的结果。好的单元测试的每个方面都同样重要,因为如果没有它们,您可能一开始就不要使用单元测试。

设置

如果您的测试依赖于特定的 sn-p 代码才能正常工作,那么您可以在适当的范围内初始化它(程序集或类初始化)。为此,您使用 [Initalize][AssemblyInitialize] 注释(大多数情况下您需要类初始化)。

重要提示:这些不是测试!

测试代码,而不是测试

再看看上面显示的代码。让我总结一下你的工作:

  • 创建模拟
  • 创建Film对象
  • 设置存储库以返回影片
  • 使用注入的模拟创建控制器
  • 断言控制器已创建
  • 断言控制器属于特定类型
  • 设置实例级变量

这是错误的,原因有 3 个:

  • 您设置了一个模拟来返回数据,但从未对其进行测试。
  • 您创建一个控制器,然后测试它是否已创建以及它是否属于正确的实例:无意义的操作可能毫无意义。
  • 您分配的实例级变量不会对其他测试产生任何影响(也不应该:请参阅良好单元测试的原则)。

您的代码中没有任何地方测试您的实际问题域,您只是在设置用于测试的东西。另请注意,您的模拟的一些更清晰的名称不会受到伤害。也不能保证单个类中的单元测试的运行顺序。

【讨论】:

  • 感谢这些提示 :) 这是我第一次进行单元测试,这些提示非常有用。
【解决方案2】:

创建一个在初始化时运行的方法,并设置需要可用于该方法中的所有测试的任何对象。 (该方法将在每次测试之前重新运行,因此不要期望状态会持续存在。)

[TestInitialize]
public void Initialize()
{
     // your common setup code here
     this.controller = ...
}

TestInitialize 是 MS Test 下的属性,类似的属性将在您可能使用的大多数其他测试框架下可用。)

我通常对将在测试中使用的存根和模拟进行此操作。至于设置我实际测试的类,我通常会在测试方法本身中处理它,或者将其重构为私有辅助方法,但这只是个人喜好。如果被测类的设置对于你所有的测试也是统一的,那么它也可以进入初始化方法。

【讨论】:

  • 是的!这正是我想要的!
【解决方案3】:

我认为你必须使用装饰器 [TestInitialize]
这用于在执行所有 [TestMethods] 之前初始化测试序列

【讨论】:

    猜你喜欢
    • 2011-07-29
    • 2016-05-28
    • 1970-01-01
    • 1970-01-01
    • 2017-06-11
    • 2020-06-13
    • 1970-01-01
    • 2016-10-24
    • 1970-01-01
    相关资源
    最近更新 更多