标签: integration-testing

如何编写数据库调用的单元测试

我已经接近一个新项目的开始了(喘气!)我第一次尝试将单元测试包含在我的项目中.

我自己设计一些单元测试时遇到了麻烦.我有一些方法很容易测试(传入两个值并检查预期的输出).我有代码的其他部分正在做更复杂的事情,比如对数据库运行查询,我不知道如何测试它们.

public DataTable ExecuteQuery(SqlConnection ActiveConnection, string Query, SqlParameterCollection Parameters)
{
    DataTable resultSet = new DataTable();
    SqlCommand queryCommand = new SqlCommand();
    try
    {
        queryCommand.Connection = ActiveConnection;
        queryCommand.CommandText = Query;

        if (Parameters != null)
        {
            foreach (SqlParameter param in Parameters)
            {
                 queryCommand.Parameters.Add(param);
            }
        }

        SqlDataAdapter queryDA = new SqlDataAdapter(queryCommand);
        queryDA.Fill(resultSet);
    }
    catch (Exception ex)
    {
        //TODO: Improve error handling
        Console.WriteLine(ex.Message);
    }

    return resultSet;
}
Run Code Online (Sandbox Code Playgroud)

此方法基本上包含从数据库中提取一些数据所需的所有必要部分,并返回DataTable对象中的数据.

第一个问题可能是最复杂的问题:在这样的情况下我应该测试什么?

一旦解决了问题,是否要模拟数据库组件或尝试对实际数据库进行测试.

database testing integration-testing unit-testing data-access-layer

63
推荐指数
4
解决办法
5万
查看次数

集成测试所需的数据库数据; 由API调用或使用导入的数据创建?

这个问题或多或少与编程语言无关.然而,由于我现在主要使用Java,所以我将从中绘制示例.我也在考虑OOP的情况,所以如果你想测试一个方法,你需要一个该方法类的实例.

一个核心规则单元测试是,他们应该是自主的,并且可以通过从它的依赖隔离一个类来实现.有几种方法可以做到这一点,这取决于你是否使用IoC注入依赖项(在Java世界中我们有Spring,EJB3和其他提供注入功能的框架/平台)和/或如果你模拟对象(对于Java你有JMockEasyMock)将正在测试的类与其依赖项分开.

如果我们需要测试不同类中的方法组*并看到它们是很好的集成,我们编写集成测试.这是我的问题!

  • 至少在Web应用程序中,状态通常持久存储在数据库中.我们可以使用与单元测试相同的工具来实现与数据库的独立性.但在我看来,我认为有些情况下,不使用数据库进行集成测试会嘲笑太多(但是可以随意反对;根本不使用数据库,这也是一个有效的答案,因为它使问题变得无关紧要).
  • 当您使用数据库进行集成测试时,如何使用数据填充该数据库?我可以看到两种方法:
    • 存储数据库内容以进行集成测试,并在开始测试之前加载它.如果它存储为SQL转储,那么数据库文件,XML或其他东西将会很有趣.
    • 通过API调用创建必要的数据库结构.这些调用可能在您的测试代码中分成几个方法,并且每个方法都可能失败.它可以被视为您的集成测试,依赖于其他测试.

当您需要时,如何确保测试所需的数据库数据?你为什么选择你选择的方法?

请提供一个动机的答案,因为这是有趣的部分所在的动机.请记住,只是说"这是最好的做法!" 这不是一个真正的动机,它只是重复你从别人那里读过或听过的东西.对于这种情况,请解释为什么这是最佳做法.

*我在单元测试的定义中包含一个在同一个类的(相同或其他)实例中调用其他方法的方法,即使它在技术上可能不正确.请随意纠正我,但让我们把它作为一个侧面问题.

testing integration-testing unit-testing mocking

58
推荐指数
4
解决办法
1万
查看次数

如何在.NET中使用真实文件进行集成测试?

我有一些类实现了一些与文件系统和文件相关的逻辑.例如,我正在执行以下任务作为此逻辑的一部分:

  • 检查某个文件夹是否具有某种结构(例如,它包含具有特定名称的子文件夹等)
  • 从这些文件夹中加载一些文件并检查它们的结构(例如,这些是一些配置文件,位于某个文件夹中的某个位置)
  • 从配置文件中加载用于测试/验证的其他文件(例如,此配置文件包含有关同一文件夹中其他文件的信息,应具有其他内部结构等...)

现在所有这些逻辑都有一些工作流程,如果某些东西不正确(例如,在特定文件夹位置找不到配置文件),则抛出异常.此外,还有Managed Extensibility Framework(MEF)涉及此逻辑,因为我检查的其中一些文件是我手动加载到MEF聚合等的托管DLL ...

现在我想以某种方式测试所有这些.我想在HDD上创建几个物理测试文件夹,涵盖各种测试用例,然后针对它们运行我的代码.我可以创建例如:

  • 文件夹结构正确,所有文件都有效
  • 文件夹结构正确但配置文件无效
  • 文件夹结构正确但缺少配置文件等...

这是正确的方法吗?我不确定在这种情况下如何运行我的代码...我当然不想运行整个应用程序并指向它来检查这些模拟的文件夹.我应该使用一些单元测试框架来编写一种"单元测试",它会针对这些文件系统对象执行我的代码吗?

总的来说,对于这种测试场景,这一切都是正确的方法吗?还有其他更好的方法吗?

.net c# integration-testing unit-testing file

58
推荐指数
2
解决办法
4万
查看次数

如何在maven安装目标中跳过测试,同时在maven测试目标中运行它们?

我有一个多模块maven项目,在同一个文件夹(src/test/java)中集成了单元测试.集成测试标有@Category(IntegrationTest.class).我想最终得到以下设置:

  1. 如果我运行mvn install,我想要编译所有测试,但我不想执行任何测试.
  2. 如果我运行mvn test,我想要编译所有测试,但只执行单元测试.
  3. 如果我运行mvn integration-test,我想编译并执行所有测试.

重要的一点是,我希望在pom.xml没有任何额外命令行参数的情况下配置它.

目前我在我的父pom.xml中提出了以下设置,其中唯一的问题是#1,其中执行所有测试:

<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>${project.java.version}</source>
                    <target>${project.java.version}</target>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.14.1</version>
                <dependencies>
                    <dependency>
                        <groupId>org.apache.maven.surefire</groupId>
                        <artifactId>surefire-junit47</artifactId>
                        <version>2.14.1</version>
                    </dependency>
                </dependencies>
                <configuration>
                    <includes>
                        <include>**/*.class</include>
                    </includes>
                    <excludedGroups>cz.cuni.xrg.intlib.commons.IntegrationTest</excludedGroups>
                </configuration>
            </plugin>

            <plugin>
                <artifactId>maven-failsafe-plugin</artifactId>
                <version>2.14.1</version>
                <dependencies>
                    <dependency>
                        <groupId>org.apache.maven.surefire</groupId>
                        <artifactId>surefire-junit47</artifactId>
                        <version>2.14.1</version>
                    </dependency>
                </dependencies>
                <configuration>
                    <groups>cz.cuni.xrg.intlib.commons.IntegrationTest</groups>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>integration-test</goal>
                            <goal>verify</goal>
                        </goals>
                        <configuration>
                            <includes>
                                <include>**/*.class</include>
                            </includes>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </pluginManagement>
</build>
Run Code Online (Sandbox Code Playgroud)

所有子模块在他们的pom.xml中都有以下插件配置,我认为它应该从父pom继承:

<build> …
Run Code Online (Sandbox Code Playgroud)

integration-testing maven maven-surefire-plugin maven-failsafe-plugin

56
推荐指数
5
解决办法
7万
查看次数

集成测试将整个对象发布到Spring MVC控制器

在集成测试spring mvc web应用程序时,有没有办法在模拟请求上传递整个表单对象?我能找到的就是将每个字段分别作为这样的参数传递:

mockMvc.perform(post("/somehwere/new").param("items[0].value","value"));
Run Code Online (Sandbox Code Playgroud)

这对于小型表格来说很好.但是,如果我发布的对象变大了怎么办?如果我可以发布整个对象,它也会使测试代码看起来更好.

具体来说,我想通过复选框测试多个项目的选择,然后发布它们.当然我可以测试发布一个项目,但我想知道..

我们使用spring 3.2.2和spring-test-mvc.

我的表单模型看起来像这样:

NewObject {
    List<Item> selection;
}
Run Code Online (Sandbox Code Playgroud)

我试过这样的电话:

mockMvc.perform(post("/somehwere/new").requestAttr("newObject", newObject) 
Run Code Online (Sandbox Code Playgroud)

到这样的控制器:

@Controller
@RequestMapping(value = "/somewhere/new")
public class SomewhereController {

    @RequestMapping(method = RequestMethod.POST)
    public String post(
            @ModelAttribute("newObject") NewObject newObject) {
        // ...
    }
Run Code Online (Sandbox Code Playgroud)

但是对象将是空的(是的,我在测试之前填充了它)

我发现唯一可行的解​​决方案就是使用@SessionAttribute: Spring MVC应用程序的集成测试:表单

但我不喜欢在我需要的每个控制器的末尾都要记得调用完成的想法.在所有表单数据不必在会话中之后,我只需要它来处理一个请求.

所以我现在唯一能想到的就是编写一些Util类,它使用MockHttpServletRequestBuilder将所有对象字段附加为.param,使用反射或单独为每个测试用例添加..

我不知道,觉得不直观..

关于如何让我变得更轻松的任何想法/想法?(除了直接调用控制器)

谢谢!

java testing spring integration-testing spring-mvc

56
推荐指数
5
解决办法
8万
查看次数

是否有用于测试"一次性"电子邮件的标准域名?

我注意到了域名

contoso.com
Run Code Online (Sandbox Code Playgroud)

当需要样本时,通常在文档中使用.我总是认为这是一个虚拟域,像电话前缀"555"一样用来将垃圾邮件路由到某种电信空白(尽管contoso.com似乎是一个真实的网站).

有一个我可以安全使用的域名,比如说,我必须使用一个独特的电子邮件地址测试一次20个注册表单,我不在乎该消息会发生什么,但我不想让它变成一个真实的人?

email integration-testing web-applications

49
推荐指数
6
解决办法
4万
查看次数

由于AppDomain,在项目之间交叉时,通过Resharper 8测试运行NUnit失败

我最近更新到Resharper 8,当我试图运行一套项目时.这些测试包含两套集成测试,它们都使用IISExpress来运行网站,发出Web请求并检查响应.

单独运行它们是成功的,并且运行所有测试之前会成功.但是,在运行后,第二组运行测试将失败.

调查显示,这AppDomain.CurrentDomain.BaseDirectory是第一次试运行而不是改变.由于集成测试由两个项目组成,这导致第二个项目失败,因为它找不到任何所需的配置文件.

我在Resharper 8中找不到任何禁用这种不同行为的选项,这似乎是/domain:Singlenunit标志的行为.没有降级到Resharper 7,有人知道解决方案吗?它是Resharper 8的预期行为还是一个bug?

c# resharper integration-testing nunit appdomain

48
推荐指数
3
解决办法
7282
查看次数

具有子域的Capybara - default_host

我有一个使用子域来切换数据库的应用程序(多租户).我正在尝试使用Capybara进行集成测试,它确实依赖于子域.

我的理解是,设置Capybara.default_host=某些内容会使我的所有请求都来自此主机.似乎并非如此.在这篇文章中,作者建议只使用主机访问显式网址,但如果我在整个地方导航,这会变得有点烦人.我想设置主机,然后能够按预期使用我的rails路径.不知道我做错了什么,但这是我尝试过的:

# spec_helper.rb
RSpec.configure do |config|
  config.before(:each, :type => :request) do
    Capybara.default_host = 'http://app.mydomain.com'
  end
end

# in some_integration_spec.rb
before do
  puts "Capybara.default_host: #{Capybara.default_host}"
  puts "some_app_url: #{some_app_url}"
end
Run Code Online (Sandbox Code Playgroud)

这产生了输出:

Capybara.default_host: http://app.mydomain.com
some_app_url: http://www.example.com/some_path
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么? default_host似乎什么都不做.正如我所说,我不想说visit(Capybara.default_host + some_app_path),因为每次都有点烦人.为什么还存在default_host选项?

integration-testing ruby-on-rails capybara

47
推荐指数
3
解决办法
2万
查看次数

使用Spring MockMVC测试Spring的@RequestBody

我正在尝试使用Spring的MockMVC框架测试将对象发布到数据库的方法.我构建了如下测试:

@Test
public void testInsertObject() throws Exception { 

    String url = BASE_URL + "/object";

    ObjectBean anObject = new ObjectBean();
    anObject.setObjectId("33");
    anObject.setUserId("4268321");
    //... more

    Gson gson = new Gson();
    String json = gson.toJson(anObject);

    MvcResult result = this.mockMvc.perform(
            post(url)
            .contentType(MediaType.APPLICATION_JSON)
            .content(json))
            .andExpect(status().isOk())
            .andReturn();
}
Run Code Online (Sandbox Code Playgroud)

我正在测试的方法使用Spring的@RequestBody来接收ObjectBean,但测试总是返回400错误.

@ResponseBody
@RequestMapping(    consumes="application/json",
                    produces="application/json",
                    method=RequestMethod.POST,
                    value="/object")
public ObjectResponse insertObject(@RequestBody ObjectBean bean){

    this.photonetService.insertObject(bean);

    ObjectResponse response = new ObjectResponse();
    response.setObject(bean);

    return response;
}
Run Code Online (Sandbox Code Playgroud)

gson在测试中创建的json:

{
   "objectId":"33",
   "userId":"4268321",
   //... many more
}
Run Code Online (Sandbox Code Playgroud)

ObjectBean类

public class ObjectBean {

private String objectId; …
Run Code Online (Sandbox Code Playgroud)

integration-testing spring-mvc

47
推荐指数
4
解决办法
9万
查看次数

Cucumber和Capybara,单击非链接或按钮元素

我正在尝试使用Cucumber/Capybara/Selenium堆栈测试一个就地编辑器,但我的问题是通过单击div而不是链接或按钮来激活编辑器.我似乎无法弄清楚如何让Capybara这样做.有办法做到这一点吗?

selenium integration-testing webdriver cucumber capybara

46
推荐指数
1
解决办法
2万
查看次数