EJB 3.0 关系/对象映射——双向一对多及多对一

假设有如下两张表
订单表:orders

字段 类型 描绘
 orderid(主键)  Int not null   订单号 
 amount  Float null  订单金额 
 createdate  Datetime  创建日期

订单项表:orderitem

字段 类型 描绘
 id(主键)  Int not null   订单项编号 
 productname  Varchar(255) not null  产品名称 
 price  Float null  产品单价
 order_id  Int null  订单号

双向一对多及多对一
Order.java

 

package demo.ejb.examples.domain;

import java.io.Serializable;
import java.sql.Date;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

@Entity
@Table(name = "Orders")
public class Order implements Serializable {

	private static final long serialVersionUID = 2092149343338263183L;
	private Integer orderid;
	private Float amount;
	private Date createdate;
	private Set<OrderItem> orderItems = new HashSet<OrderItem>();

	@Id
	@GeneratedValue
	public Integer getOrderid() {
		return orderid;
	}

	public void setOrderid(Integer orderid) {
		this.orderid = orderid;
	}

	public Float getAmount() {
		return amount;
	}

	public void setAmount(Float amount) {
		this.amount = amount;
	}

	@Temporal(value = TemporalType.TIMESTAMP)
	public Date getCreatedate() {
		return createdate;
	}

	public void setCreatedate(Date createdate) {
		this.createdate = createdate;
	}

	@OneToMany(mappedBy = "order", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
	@OrderBy(value = "id ASC")
	public Set<OrderItem> getOrderItems() {
		return orderItems;
	}

	public void setOrderItems(Set<OrderItem> orderItems) {
		this.orderItems = orderItems;
	}

}

 

 

OrderItem.java

 

package demo.ejb.examples.domain;

import java.io.Serializable;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name = "OrderItems")
public class OrderItem implements Serializable {

	private static final long serialVersionUID = 4255254187929539251L;
	private Integer id;
	private String productname;
	private Float price;
	private Order order;
	
	@Id
	@GeneratedValue
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	
	@Column(length = 255, nullable = false)
	public String getProductname() {
		return productname;
	}
	public void setProductname(String productname) {
		this.productname = productname;
	}
	
	public Float getPrice() {
		return price;
	}
	public void setPrice(Float price) {
		this.price = price;
	}
	
	@ManyToOne(cascade = CascadeType.REFRESH, optional = false)
	@JoinColumn(name = "order_id")
	public Order getOrder() {
		return order;
	}
	public void setOrder(Order order) {
		this.order = order;
	}
	
	
}

 

 

List of freely available programming books

Meta-Lists

Graphics Programming

Language Agnostic

ASP.NET MVC

Assembly Language

Bash

C / C++

C#

  • See .NET below

Clojure

DB2

Delphi / Pascal

Django

Erlang

Flex

F#

Forth

Git

Grails

Haskell

HTML / CSS

Java

JavaScript

Linux

Lisp

Lua

Maven

Mercurial

Nemerle

  • See .NET below

.NET (C# / VB / Nemerle / Visual Studio)

NoSQL

Oberon

Objective-C

OCaml

Oracle Server

Oracle PL/SQL

Parrot / Perl 6

Perl

PHP

PowerShell

Prolog

PostgreSQL

Python

R

Ruby

Ruby on Rails

Scala

Scheme

Smalltalk

Subversion

SQL (implementation agnostic)

Vim

Websphere

createMock,createNiceMock and createStrictMock的区别

EasyMock.createMock(): Creates a mock object that implements the given interface, order

checking is disabled by default.

 

EasyMock.createNiceMock() : Creates a mock object that implements the given interface, order checking is disabled by default, and

the mock object will return 0, null or false for unexpected invocations.

 

EasyMock.createStrickMock() : Creates a mock object that implements the given interface, order

checking is enabled by default.

 

A Dmoe Of EasyMock

List 1:测试类 Authenticator.java

 

package com.rolyer.session;

import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.log.Log;
import org.jboss.seam.security.Credentials;
import org.jboss.seam.security.Identity;

@Name("authenticator")
public class Authenticator
{
    @Logger private Log log;

    @In Identity identity;
    @In Credentials credentials;

    public boolean authenticate()
    {
        log.info("authenticating {0}", credentials.getUsername());
        //write your authentication logic here,
        //return true if the authentication was
        //successful, false otherwise
        if ("admin".equals(credentials.getUsername()))
        {
            identity.addRole("admin");
            return true;
        }
        return false;
    }
}

 

 
List 2:测试用例 AuthenticatorTest.java

 

package com.rolyer.session;

import org.easymock.classextension.EasyMock;
import org.jboss.seam.log.Log;
import org.jboss.seam.security.Credentials;
import org.jboss.seam.security.Identity;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import com.rolyer.sms.util.TestUtils;

public class AuthenticatorTest {

	private Authenticator authenticator;

	private Log log;
	private Identity identity;
	private Credentials credentials;

	@BeforeMethod
	public void beforeMethod() {
		authenticator = new Authenticator();
                //创建模仿对象的实例
		log = EasyMock.createMock(Log.class);
		identity = EasyMock.createMock(Identity.class);
		credentials = EasyMock.createMock(Credentials.class);
	}

	@AfterMethod
	public void afterMethod() {
		authenticator = null;

		log = null;
		identity = null;
		credentials = null;
	}

	@Test
	public void testAuthenticateWithNotAdmin() throws Exception {
                 //创建模仿对象的实例
		// Log log = EasyMock.createMock(Log.class);
		// Identity identity = EasyMock.createMock(Identity.class);
		// Credentials credentials = EasyMock.createMock(Credentials.class);

                //设置模仿对象中的状态和期望值
		EasyMock.expect(credentials.getUsername()).andReturn("user").times(2);

                //将模仿对象作为参数来调用域代码
		TestUtils.setProperty(authenticator, "log", log);
		TestUtils.setProperty(authenticator, "identity", identity);
		TestUtils.setProperty(authenticator, "credentials", credentials);

                //切换到replay状态
		EasyMock.replay(credentials);

		boolean result = authenticator.authenticate();

		assert !result;

                //验证模仿对象中的一致性
		EasyMock.verify(credentials);
	}

	@Test
	public void testAuthenticateWithAdmin() throws Exception {
		// Log log = EasyMock.createMock(Log.class);
		// Identity identity = EasyMock.createMock(Identity.class);
		// Credentials credentials = EasyMock.createMock(Credentials.class);

		EasyMock.expect(credentials.getUsername()).andReturn("admin").times(2);

		TestUtils.setProperty(authenticator, "log", log);
		TestUtils.setProperty(authenticator, "identity", identity);
		TestUtils.setProperty(authenticator, "credentials", credentials);

		EasyMock.replay(credentials);

		boolean result = authenticator.authenticate();

		assert result;

		EasyMock.verify(credentials);
	}

}

 

 
List 3:辅助类 TestUtils.java

 

package com.rolyer.sms.util;

import java.lang.reflect.Field;

public class TestUtils {
	public static void setProperty(Object obj, String propertyName,
			Object property) throws Exception {

		Class<?> usersDAOClazz = obj.getClass();

		Field emField = usersDAOClazz.getDeclaredField(propertyName);
		emField.setAccessible(true);
		emField.set(obj, property);
	}
}

 

 
注:Authenticator.java是JBoss Seam的登录代码。

Unit Testing With Mock

Unit Testing With Mock

Agenda

  • What is mocking?
  • Why to use mocking?
  • Types of mocking
  • Easymock
  • Simple Examples of EasyMock(with extensions) and PowerMock

What is mocking?

  • Mocking allows you to test a class or method in isolation .
  • A class/method maybe dependent on many other classes/methods. It is with the help of others(collaborators) a class/method completes itz functionality.
  • In mocking we replace all of its collaborators with mocks that essentially simulate the normal environment of the class/method.
  • In other words: “A mock object is a dummy interface or class in which you define the dummy output of a certain method call.”

Why to use mocking?

  • In mocking we replace all of its collaborators with mocks;
  • DATABASE is not required so NO dbunit;
  • Use of Context is avoided;
  • Dependencies can be ignored;
  • We just test the core functinality of the class/method and we dont have to test the collaborators;
  • Easy;
  • less time to write junit for complex legacy code.

How Mock Objects Work?

2 Types in general

  • Proxy based like easymock,jmock
  • remap the class file in the class loader like jmockit ,powermock

1. Proxy based

  • Reflection : Java's Reflection API's makes it possible to inspect classes, interfaces, fields and methods at runtime, without knowing the names of the classes, methods etc. at compile time.
  • It is also possible to instantiate new objects, invoke methods and get/set field values using reflection.
  • Using Java Reflection you create dynamic implementations of interfaces at runtime. You do so using the class java.lang.reflect.Proxy
  • you can set what return values the proxy must return.
  • Proxy is a special class that allows intercept a set of methods identified by an interface public Object invoke(Object proxy, Method method, Object[] args)
  • a proxy object is used to imitate the real object your code is dependent on.

2. Remap the class file

you tell the class loader to remap the reference to the class file it will load. So let's say that I have a class Employeee with the corresponding .class file called Employeee.class and I want to mock it to use MyMock instead. By using this type of mock objects, you will actually remap in the classloader the reference from Employeee to MyMock.class. Uses the Instrumentation API.

What is EasyMock?

  • http://easymock.org/
  • easymock framework helps you create mock objects.
  • Others are : jmock / Mockito / rMock / jMockit / sevenMock

How to use easymock?

  • Create a mock SomeInterface mock = createMock ( SomeInterface.class );
  • Record behavior expect( mock.doStuff( "argument" )).andReturn( "returnValue" );
  • Replay behaviour replay( mock );
  • Executing the code we want to test String newValue=test.perform() assume perform() method calls doStuff() method.
  • Verify behaviour verify(mock).

Step 1 : Create a Mock

  • Identify the classes/methods which are the collaborators.We can mock the classes by first mockin the Interface
  • createMock method is used to create the mock object. stmtMock = createMock ( Statement.class ) ;

Step 2 : Mock the methods

  • In EasyMock we use a record / replay approach.
  • record means -->You first train the mock by making the expected method calls on it .
  • replay means -->it tells EasyMock to stop recording . After that, it calls on the object to return the set values. If it gets a call it does not expect, it throws an Exception to fail fast.
  • It does not actually replay the mock. BUT it resets the mock so that the next time its methods are called it will begin replaying. st.executeQuery("SELECT * FROM survey"); expect(stmtMock.executeQuery("SELECT * FROM survey")).andReturn(rsMock);

Step 3 : Execute the code to test

  • AssertEquals ( 55 , idao.getNoOfColumns() );

Step 4 : Verify the behaviour

  • verify means-->verify( ) method checks to see if the mock actually received all the calls you expect
  • The method is used to make sure that all of the behaviour expected from the collaborators is valid. verify (stmtMock);

Syntax

  • To Throw An Exception
    expect(mock.method()).andThrow(expectedException);
  • Expecting A Method With void Return Type
    mock.clear();
    ExpectLastCall();
  • Need to mention no. Of calls
    expectLastCall().times(3);
  • Argument Matchers
    eq(X value)
    isA(Class clazz)
    anyBoolean(), anyByte(), anyChar(), anyDouble(), anyFloat(), anyInt(),anyLong(), anyObject(), anyShort()

Drawbacks of easymock

  • Cannot mock static methods
  • Cannot mock private methods
  • Cannot mock final methods
  • Cannot mock concrete classes
  • Cannot mock Constructors
  • jMock does not force us to put expectations on things that are irrelevant to the test at hand. If we're testing Cache.add(), it does not matter what the underlying call to Map.put() returns. With EasyMock, we have to fully specify everything, whether it matters or not

Types of objects in easymock

  • Normal — createMock(): All of the expected methods must be called with the specified arguments. However, the order in which these methods are called does not matter. Calls to unexpected methods cause the test to fail.
  • Strict — createStrictMock(): All expected methods must be called with the expected arguments, in a specified order. Calls to unexpected methods cause the test to fail.
  • Nice — createNiceMock(): All expected methods must be called with the specified arguments in any order. Calls to unexpected methods do not cause the test to fail. Nice mocks supply reasonable defaults for methods you don't explicitly mock. Methods that return numbers return 0. Methods that return booleans return false. Methods that return objects return null.

Use of verify

  • The verify phase confirms the execution of the expected calls.
  • Useful in case of strict Mocks,where you need to check whether you called the methods,in right order.It will show all missing method calls.
  • In case of regular mocks it is not necessary.

Repeated calls

  • For every method invoked by the mock we need an expectation.
  • By default mock expects minimum 1 call.
  • times(int min, int max) : to expect between min and max calls,
  • AtLeastOnce() : to expect at least one call, and
  • AnyTimes() : to expected an unrestricted number of calls.

Matchers in EasyMock

  • eq(X value) : Matches if the actual value is equals the expected value. Available for all primitive types and for objects.
  • IsNull() : Matches if the actual value is null. Available for objects.
  • NotNull() : Matches if the actual value is not null. Available for objects.
  • startsWith(String prefix), contains(String substring), endsWith(String suffix) : Matches if the actual value starts with/contains/ends with the given value. Available for Strings.
  • matches(String regex), find(String regex) : Matches if the actual value/a substring of the actual value matches the given regular expression. Available for Strings.