2015年6月5日星期五

《Entity Framework 6 Recipes》中文翻译系列 (46) ------ 第八章 POCO之领域对象测试和仓储测试 - china_fucan

本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订
《Entity Framework 6 Recipes》中文翻译系列 (46) ------ 第八章 POCO之领域对象测试和仓储测试 - china_fucan  阅读原文»

翻译的初衷以及为什么选择《Entity Framework 6 Recipes》来学习,请看本系列开篇

8-8 测试领域对象

问题

  你想为领域对象创建单元测试。

  这主要用于,测试特定的数据访问功能。

解决方案

  对于这个解决方案,使用POCO模板来创建你的实体。使用POC模板能减少你需要编写的代码量,还能让你的解决方案非常清晰。当然,在解决方案中,你将运用手工创建的POCO类和下面的步骤。

  假设你有如图8-9所示的模型。

图8-9. 一个包含reservation、schedule和train的模型

  这个模型表示预订火车出行。每个预定都是一个特定的出行计划。按下面的步骤创建模型和为应用准备单元测试:

    1、创建一个空的解决方案。右键解决方案,选择Add(新增) New Project(新建项目)。添加一个类库项目。将它命名为TrainReservation;

    2、右键TrainReservation项目,选择Add(新增) New Item(新建项)。添加一个ADO.NET实体数据模型。导入表Train,Schedule和Reservation。最终的模型如图8-9所示。

    3、添加一个Ivalidate接口和ChangeAction枚举,如代码清单8-11所示。

代码清单8-11. IValidate接口

public enum ChangeAction
{
Insert,
Update,
Delete
}
interface IValidate
{
void Validate(ChangeAction action);
}

    4、将代码8-12中的代码添加到项目中,它添加了类Reservation和Schedule的验证代码(实现接口IValidate)。

代码清单8-12. 类Reservation和Schedule类实现IValidate接口

1 public partial class Reservation : IValidate
2 {
3 public void Validate(ChangeAction action)
4 {
5 if (action == ChangeAction.Insert)
6 {
7 if (Schedule.Reservations.Count(r =>
8 r.ReservationId != ReservationId &&
9 r.Passenger == this.Passenger) > 0)
10 throw new InvalidOperationException(
11 "Reservation for the passenger already exists");
12 }
13 }
14 }
15
16 public partial class Schedule : IValidate
17 {
18 public void Validate(ChangeAction action)
19 {
20 if (action == ChangeAction.Insert)
21 {
22 if (ArrivalDate < DepartureDate)
23 {
24 throw new InvalidOperationException(
25 "Arrival date cannot be before departure date");
26 }
27
28 if (LeavesFrom == ArrivesAt)
29 {
30 throw new InvalidOperationException(
31 "Can't leave from and arrive at the same location");
32 }
33 }
34 }
35 }

    5、使用代码清单8-13中的代码重写DbContext中的SaveChanges()方法,这将允许你在保存数据到数据库前验证更改。

代码清单8-13. 重写SaveChages()方法

1 public override int SaveChanges()
2 {
3 this.ChangeTracker.DetectChanges();
4 var entries = from e in this.ChangeTracker.Entries().Where(e => e.State == (System.Data.Entity.EntityState.Added | EntityState.Modified | EntityState.Deleted))
5 where (e.Entity != null) &&
6 (e.Entity is IValidate)
7 select e;
8 foreach (var entry in entries)
9 {
10 switch (entry.State)
11 Java知多少(84)图形界面之布局设计 - Coda  阅读原文»

在界面设计中,一个容器要放置许多组件,为了美观,为组件安排在容器中的位置,这就是布局设计。java.awt中定义了多种布局类,每种布局类对应一种布局的策略。常用的有以下布局类:

  • FlowLayout,依次放置组件。
  • BoarderLayout,将组件放置在边界上。
  • CardLayout,将组件像扑克牌一样叠放,而每次只能显示其中一个组件。
  • GridLayout,将显示区域按行、列划分成一个个相等的格子,组件依次放入这些格子中。
  • GridBagLayout,将显示区域划分成许多矩形小单元,每个组件可占用一个或多个小单元。

其中GridBagLayout能进行精细的位置控制,也最复杂,本教程暂不讨论这种布局策略,将在专题文章中进行详细讲解。

每个容器都有一个布局管理器,由它来决定如何安排放入容器内的的组件。布局管理器是实现LayoutManager接口的类。

一.FlowLayout布局 (JApplet,JPanel,JScrollPane默认布局)

FlowLayout布局是将其中的组件按照加入的先后顺序从左到右排列,一行满之后就转到一下行继续从左到右排列,每一行中的组件都居中排列。这是一种最简便的布局策略,一般用于组件不多的情况,当组件较多时,容器中的组件就会显得高低不平,各行长短不一。

FlowLayout是小应用程序和面板默认布局,FlowLayout布局的构造方法有:

  1. FlowLayout(),生成一个默认的FlowLayout布局。默认情况下,组件居中,间隙为5个像素。
  2. FlowLayout(int aligment),设定每珩的组件的对齐方式。alignment取值可以为 FlowLayout.LEFT,FlowLayout.CENTER,FlowLayout.RIGHT。
  3. FlowLayout(int aligment,int horz, int vert),设定对齐方式,并设定组件的水平间距horz和垂直间距vert,用超类Container的方法setLayout()为容器设定布局。例如,代码setLayout(new FlowLayout())为容器设定 FlowLayout布局。将组件加入容器的方法是add(组件名)。

二.BorderLayout布局(JWindow、JFrame,JDialog的默认布局)

BorderLayout布局策略是把容器内的空间简单划分为东“East”,西 “West”,南 “South”,北 “North”,中 “Center”五个区域。加入组件时,都应该指明把组件放在哪一个区域中。一个位置放一个组件。如果某个位置要加入多个组件,应先将要加入该位置的组件放放另一个容器中,然后再将这个容器加入到这个个位置。

BorderLayout布局的构造方法有:
(1) BorderLayout(),生成一个默认的BorderLayout布局。默认情况下,没有间隙。
(2) BorderLayout(int horz,int vert),设定组件之间的水平间距和垂直间距。

BorderLayout布局策略的设定方法是setLayout(new BorderLayout())。将组件加入到容器的方法是add(组件名,位置),如果加入组件时没有指定位置,则默认为“中”位置。

BorderLayout布局是JWindow、JFrame,JDialog的默认布局。
【例 11-5】应用程序设有五个标签、分别放于窗口的东、西、南、北和中五个区域。

1 import javax.swing.*;import java.awt.*;
2 public class J505{
3 public static void main(String[]args){
4 JLabel label1,label2,label3,label4,label5;
5 JFrame mw=new JFrame("我是一个窗口");//创建一个窗口容器对象
6 mw.setSize(250,200);
7 Container con=mw.getContentPane();
8 con.setLayout(new BorderLayout());
9 label1=new JLabel("东标签");//默认左对齐
10 label2=new JLabel("南标签",JLabel.CENTER);
11 label3=new JLabel("西标签");
12 label4=new JLabel("北标签",JLabel.CENTER);
13 label5=new JLabel("中标签",JLabel.CENTER);
14 con.add(label1,"East");
15 con.add(label2,"South");
16 con.add(label3,"West");
17 con.add(label4,"North");
18 con.add(label5,"Center");
19 mw.setVisible(true);
20 }
21 }

三.GridLayout布局

GridLayout布局是把容器划分成若干行和列的网格状,行数和列数由程序控制,组件放在网格的小格子中。GridLayout布局的特点是组件定位比较精确。由于GridLayout布局中每个网格具有相同形状和大小,要求放入容器的组件也应保持相同的大小。

GridLayout布局的构造方法有:
(1) GridLayout(),生成一个单列的GridLayout布局。默认情况下,无间隙。
(2) GridLayout(int row,int col),设定一个有行row和列col的GridLayout布局。
(3) GridLayout(int row,int col,int horz,int vert),设定布局的行数和列数、组件的水平间距和垂直间距。

GridLayout布局以行为基准,当放置的组件个数超额时,自动增加列;反之,组件太少也会自动减少列,行数不变,组件按行优先顺序排列(根据组件自动增减列)。GridLayout布局的每个网格必须填入组件,如果希望某个网格为空白,可以用一个空白标签(add(new Label()))顶替。

【例 11-6】小应用程序先将若干个按钮和若干个标签放入JPanel中,然后将JPanel放入JScrollPane中,最后,将JScrollPane放入小程序的窗口中,程序所创建的JScrollPane总是带水平和垂直滚动条,滚动面板的可视范围小于面板的实际要求,可以移动滚动条的滑块显示面板原先不在可视范围内的区域。

1 import java.applet.*;
2 import javax.swing.*;
3 import java.awt.*;
4 class MyWindow extends JFrame{
5 public MyWindow(int w,int h){
6 setTitle("滚动面板实例");
7 Container con=getContentPane();
8 con.setPreferredSize(new Dimension(w,h));
9 con.setLayout(new BorderLayout());
10 JPanel p=new JPanel();
11 p.setLayout(new GridLayout(6,6));
12 for (int i=0;i<6;i++){
13 p.add(new JLabel());
14 for(int j=1;j<=2;j++){
15 p.add(new JButton("按钮"+(2*i+j)));
16 p.add(new JLabel("标签"+(2*i+j)));
17 }
18 p.add(new JLabel());
19 }
20 阅读更多内容

没有评论:

发表评论