我有两个控制器都在Play 2.0中使用AKKA演员。因此,有两个测试用例针对这两个API进行测试。但是,执行'play test'时,只有一个测试用例会成功,另一个测试用例会失败。如果我单独运行它,它会成功运行。我的预感是演员系统已经被第一次测试关闭了。但是,我是Play 2和Akka的新手,这只是我的猜测。有解决方法吗?
@Test
public void callPostA() {
running(testServer(2222, fakeApplication(inMemoryDatabase())), new Runnable() {
@Override
public void run() {
HttpPost httpPost = new HttpPost("http://localhost:2222/controllera");
....
}
});
}
@Test
public void callPostB() {
running(testServer(2222, fakeApplication(inMemoryDatabase())), new Runnable() {
@Override
public void run() {
HttpPost httpPost = new HttpPost("http://localhost:2222/controllerb");
....
}
});
}
两个控制器如下:
public class PostA extends Controller {
// master actor for workers
public static ActorRef masterActorA = Akka.system().actorOf(new Props(new UntypedActorFactory() {
public UntypedActor create() {
return new PostAActorMaster(Config.NUMBER_OF_WORKER_ACTOR);
}
}), "PostAActorMaster");
public static Result postA() {
Map<String, String[]> dict = body.asFormUrlEncoded();
String paramField1 = dict.get("paramField1");
String paramField2 = dict.get("paramField2");
ProductInfo pInfo = new ProductInfo(paramField1, paramField2);
ProductMessage pMessage = new ProductMessage(pInfo);
return async(
Akka.asPromise(ask(masterActorA, pMessage, 15000)).map(
new Function<Object, Result>() {
...
}
));
}
public class PostB extends Controller {
// master actor for workers
public static ActorRef masterActorB = Akka.system().actorOf(new Props(new UntypedActorFactory() {
public UntypedActor create() {
return new PostBActorMaster(Config.NUMBER_OF_WORKER_ACTOR);
}
}), "PostBActorMaster");
public static Result postB() {
Map<String, String[]> dict = body.asFormUrlEncoded();
String paramField3 = dict.get("paramField3");
String paramField4 = dict.get("paramField4");
BillInfo bInfo = new BillInfo(paramField3, paramField4);
BillMessage pMessage = new BillMessage(bInfo);
return async(
Akka.asPromise(ask(masterActorB, pMessage, 15000)).map(
new Function<Object, Result>() {
...
}
));
}
PostA的AKKA大师和工人:
public class PostAActorMaster extends UntypedActor {
private final ActorRef workerRouter;
public PostAActorMaster(final int nrOfWorkers) {
workerRouter = this.getContext().actorOf(new Props(PostAActorMaster.class).withRouter(new RoundRobinRouter(nrOfWorkers)));
}
public void onReceive(Object messageObj) {
try {
if (messageObj instanceof ProductMessage) {
// invoke worker to submit channel messaages
workerRouter.tell(messageObj, getSender());
} else if (messageObj instanceof ProductMessageResult) {
......
getSender().tell("OK");
}
} catch (Exception e) {
......
}
}
}
public class PostAActorWorker extends UntypedActor {
public void onReceive(Object messageObj) throws Exception {
if (messageObj instanceof ProductMessage) {
ProductMessage pMessage = (ProductMessage)messageObj;
ProductInfo pInfo = pMessage.getProductInfo();
log.info(pInfo.getProductId());
ProductMessageResult pr = new ProductMessageResult(pInfo);
PostA.masterActor.tell(pr, getSender());
}
}
}
托管对象:
public class ProductInfo extends Model {
@Id
private String productId;
...
}
答案 0 :(得分:1)
我不再看到问题了。这是我的测试用例的结构。也许你可以尝试一下,看看它是否适合你。
Scala的:
object LoginApiTest extends PlaySpecification {
"login api quick login" should {
"post login data" in new WithCleanTestData {
var org1 = new OrgInfo("testorg", "Test Inc");
org1.save();
}
}
}
abstract class WithCleanTestData extends WithApplication(FakeApplication(
additionalConfiguration = TestConf.getConf.toMap
)) {
override def around[T: AsResult](t: => T): Result = super.around {
prepareDbWithData()
t
}
def prepareDbWithData() = {
OrgInfo.getAllOrgInfo.foreach(_.delete)
}
}
爪哇:
public class MyHelpers extends Helpers {
public static FakeApplication myFakeApplication(Map<String,String> additionalConfiguration) {
List<String> withoutPlugins = new ArrayList<String>();
List<String> additionalPlugins = new ArrayList<String>();
return new MyFakeApplication(new java.io.File("."), MyHelpers.class.getClassLoader(),
additionalConfiguration, withoutPlugins, additionalPlugins, null);
}
}
public class BaseModelTest extends WithApplication {
@Before
public void before() {
}
}
public class PostTest extends BaseModelTest {
@Test
public void test1() {
}
}
此外,您可以尝试将此设置添加到Build.scala:
parallelExecution in Test := false
答案 1 :(得分:0)
嘿我使用的是静态ActorSystem,这导致了一个问题
[error] sbt.ForkMain$ForkError: Error creating bean with name 'accountServiceController' defined in file [/Users/admin/Development/src/totes/app/target/scala-2.11/classes/controllers/AccountServiceController.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [controllers.AccountServiceController]: Constructor threw exception; nested exception is java.lang.IllegalStateException: cannot create children while terminating or terminated
通过创建每次应用程序启动时创建的动态ActorSystem,问题似乎消失了。 我在这方面工作了一段时间,所以我想在此发布这个潜在的解决方案。