测试涉及数据库

时间:2017-06-17 14:33:36

标签: node.js unit-testing express testing jasmine

在指出我的问题之前,我想告诉我我是测试领域的新手,所以这是我的问题:

我使用express + sequelize(mysql)开发了一个rest api,我想为我的api编写一些测试。我选择使用茉莉花库进行测试。

所以我知道我想测试createupdate休息端点,我需要访问数据库,但问题是测试用例并行运行,并且只有一个数据库,所以如果我想从测试用例中的表中删除所有项目,而另一个测试用例在该表中创建了一行,则会出现问题。

const request = require('superagent');

const models = require('../../src/models');
const Station = models.Station;

describe("station testing", function () {


    before(() => {
        // delete and recreate all database table
        // before running any test
    });


    describe("crud station", function () {
        it('should create model', () => {

            Station.create({
                'name': 'test',
                lat: 12,
                long: 123,
            }).then( model => {
                expect(model).toBeTruthy();
            });

        });

           it('should delete evrything', () => {


            Station.deleteAll().then( () => {

                // problem here if after the first model is created and before create model except is executed 
                 expect(Station.Count()).toEqual(0);
            }


        });

    });



});

2 个答案:

答案 0 :(得分:1)

Jasmine支持beforeEach的函数,该函数在describe块中的每个规范之前运行。 你可以使用它。

describe("A spec using beforeEach and afterEach", function() { 
  var foo = 0; 
  beforeEach(function() { foo += 1; });
  afterEach(function() { foo = 0; }); 
  it("is just a function, so it can contain any code", function() { 
    expect(foo).toEqual(1);
  }); 
  it("can have more than one expectation", function() { 
    expect(foo).toEqual(1)
    expect(true).toEqual(true); 
  }); 
});

所以你可以让beforeEach处理删除操作。

答案 1 :(得分:1)

你的问题是你不是在这里写单元测试。

您需要了解最重要的单元测试规则 - 一次只测试一个单元。可以将单元视为代码的一个区域。在传统的桌面项目(Java,C#等)中,一个单元将是一个类。在Javascript的情况下,单元更难定义,但肯定包含Javacript。如果您在测试中包含任何服务器代码(例如,数据库),那么您不是单元测试,而是进行集成测试(这也非常重要,但更难)。

您的Javascript将具有依赖项(即它调用的其他代码,例如通过Ajax调用),在您的情况下将包含被调用的服务器代码。为了进行单元测试,您需要确保测试Javascript,这意味着在运行测试时,您根本不希望调用服务器代码。这样,您可以隔离该代码单元中的任何错误,并且可以确信发现的任何问题确实存在于该单元中。如果您包含其他单位,则可能是其他单位遇到问题。

在强类型语言(如Java,C#等)中,有一些框架允许您为每个依赖项设置模拟。虽然我自己没有尝试过(本周的工作),但有mocking frameworks for Javascript,您可能需要使用其中一个来进行真正的单元测试。你模拟了服务器代码,所以当你运行测试时,它实际上并没有真正命中数据库。除了解决您的问题之外,它还避免了您在当前方法中可能遇到的其他问题。

如果您不想使用模拟框架,另一种方法是更改​​您的Javascript,以便您正在测试的功能需要一个额外的参数,这是一个执行实际服务器调用的函数。所以,而不是......

deleteCustomer(42);

deleteCustomer(id) {
  validate(id);
  $.ajax(...);
}

...你的代码看起来像这样......

deleteCustomer(42, callServer);

deleteCustomer(id, serverCall) {
  validate(id);
  serverCall(id);
}

...其中serverCall()包含Ajax调用。

然后,对于单元测试,你会测试这样的东西......

deleteCustomer(42, function(){});

...所以不是调用服务器,实际上什么也没做。

这显然需要对代码进行一些重写,这可以通过模拟来避免,但可以正常工作。我的建议是花一些时间学习如何使用模拟框架。从长远来看,它会得到回报。

对不起,这已经有点长了。不幸的是,您正在进入一个复杂的单元测试领域,了解您正在做的事情非常重要。我强烈建议您在进一步了解之前阅读有关单元测试的内容,因为对基础知识的充分理解将为您节省很多麻烦。罗伯特·马丁(又名鲍勃叔叔)关于这个问题的任何内容都会很好,但网上有很多资源。

希望这会有所帮助。如果您想了解更多信息或澄清,请随时提出。