我已经接近一个新项目的开始了(喘气!)我第一次尝试将单元测试包含在我的项目中.
我自己设计一些单元测试时遇到了麻烦.我有一些方法很容易测试(传入两个值并检查预期的输出).我有代码的其他部分正在做更复杂的事情,比如对数据库运行查询,我不知道如何测试它们.
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
这个问题或多或少与编程语言无关.然而,由于我现在主要使用Java,所以我将从中绘制示例.我也在考虑OOP的情况,所以如果你想测试一个方法,你需要一个该方法类的实例.
一个核心规则的单元测试是,他们应该是自主的,并且可以通过从它的依赖隔离一个类来实现.有几种方法可以做到这一点,这取决于你是否使用IoC注入依赖项(在Java世界中我们有Spring,EJB3和其他提供注入功能的框架/平台)和/或如果你模拟对象(对于Java你有JMock和EasyMock)将正在测试的类与其依赖项分开.
如果我们需要测试不同类中的方法组*并看到它们是很好的集成,我们编写集成测试.这是我的问题!
当您需要时,如何确保测试所需的数据库数据?你为什么选择你选择的方法?
请提供一个动机的答案,因为这是有趣的部分所在的动机.请记住,只是说"这是最好的做法!" 这不是一个真正的动机,它只是重复你从别人那里读过或听过的东西.对于这种情况,请解释为什么这是最佳做法.
*我在单元测试的定义中包含一个在同一个类的(相同或其他)实例中调用其他方法的方法,即使它在技术上可能不正确.请随意纠正我,但让我们把它作为一个侧面问题.
我有一些类实现了一些与文件系统和文件相关的逻辑.例如,我正在执行以下任务作为此逻辑的一部分:
现在所有这些逻辑都有一些工作流程,如果某些东西不正确(例如,在特定文件夹位置找不到配置文件),则抛出异常.此外,还有Managed Extensibility Framework(MEF)涉及此逻辑,因为我检查的其中一些文件是我手动加载到MEF聚合等的托管DLL ...
现在我想以某种方式测试所有这些.我想在HDD上创建几个物理测试文件夹,涵盖各种测试用例,然后针对它们运行我的代码.我可以创建例如:
这是正确的方法吗?我不确定在这种情况下如何运行我的代码...我当然不想运行整个应用程序并指向它来检查这些模拟的文件夹.我应该使用一些单元测试框架来编写一种"单元测试",它会针对这些文件系统对象执行我的代码吗?
总的来说,对于这种测试场景,这一切都是正确的方法吗?还有其他更好的方法吗?
我有一个多模块maven项目,在同一个文件夹(src/test/java)中集成了单元测试.集成测试标有@Category(IntegrationTest.class).我想最终得到以下设置:
mvn install,我想要编译所有测试,但我不想执行任何测试.mvn test,我想要编译所有测试,但只执行单元测试.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
在集成测试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,使用反射或单独为每个测试用例添加..
我不知道,觉得不直观..
关于如何让我变得更轻松的任何想法/想法?(除了直接调用控制器)
谢谢!
我注意到了域名
contoso.com
Run Code Online (Sandbox Code Playgroud)
当需要样本时,通常在文档中使用.我总是认为这是一个虚拟域,像电话前缀"555"一样用来将垃圾邮件路由到某种电信空白(尽管contoso.com似乎是一个真实的网站).
有一个我可以安全使用的域名,比如说,我必须使用一个独特的电子邮件地址测试一次20个注册表单,我不在乎该消息会发生什么,但我不想让它变成一个真实的人?
我最近更新到Resharper 8,当我试图运行一套项目时.这些测试包含两套集成测试,它们都使用IISExpress来运行网站,发出Web请求并检查响应.
单独运行它们是成功的,并且运行所有测试之前会成功.但是,在运行后,第二组运行测试将失败.
调查显示,这AppDomain.CurrentDomain.BaseDirectory是第一次试运行而不是改变.由于集成测试由两个项目组成,这导致第二个项目失败,因为它找不到任何所需的配置文件.
我在Resharper 8中找不到任何禁用这种不同行为的选项,这似乎是/domain:Singlenunit标志的行为.没有降级到Resharper 7,有人知道解决方案吗?它是Resharper 8的预期行为还是一个bug?
我有一个使用子域来切换数据库的应用程序(多租户).我正在尝试使用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选项?
我正在尝试使用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) 我正在尝试使用Cucumber/Capybara/Selenium堆栈测试一个就地编辑器,但我的问题是通过单击div而不是链接或按钮来激活编辑器.我似乎无法弄清楚如何让Capybara这样做.有办法做到这一点吗?