我有一个伞形项目由:
组成这三个组件通过AMQP连接,因此它们可以在它们之间发送和接收消息。
我们正在使用Docker,并且在google cloud的kubernetes引擎上托管了drone.io。所以,正在发生的是随机应用程序在运行我的测试时引发以下异常:
import com.vaadin.ui.*;
import java.util.function.Consumer;
// confirmation window
public class ConfirmationWindow {
private Integer value;
public ConfirmationWindow(Integer value) {
this.value = value;
}
public void showModal(Consumer<Boolean> resultCallback) {
Window window = new Window("Confirm transaction");
window.setContent(
new VerticalLayout(
new Label("Your account will be charged with " + (value / 100) + " for this transaction, are you sure you want to continue?"),
new HorizontalLayout(
new Button("Ok", event -> {
resultCallback.accept(true);
window.close();
}),
new Button("Cancel", event -> {
resultCallback.accept(false);
window.close();
})
)
)
);
window.setModal(true);
getUI().addWindow(window);
}
}
这是一个Json,因为我们在测试中交换了amqp消息,例如:
import com.vaadin.data.Binder;
import com.vaadin.data.converter.StringToIntegerConverter;
import com.vaadin.ui.*;
public class TransactionForm extends FormLayout {
private static final String FEE_ACCEPTED_MESSAGE = "Press the save button to view the transaction fee and confirm";
// initial withdrawal mount
private Integer value = 0;
// used to make binder "invalid" until confirmation dialog is closed with "Ok"
private Boolean customerAcceptedAtmFee = false;
public TransactionForm() {
// some existing bean (eg, loaded from DB for editing)
BankAccount bean = new BankAccount(1000);
// form components
TextField currentAmount = new TextField("Available");
TextField withdrawalAmount = new TextField("Withdraw");
// binder setup
Binder<BankAccount> accountBinder = new Binder<>(BankAccount.class);
Label statusLabel = new Label();
accountBinder.setStatusLabel(statusLabel);
// consider valid only if the client has also accepted to pay the fee
accountBinder.withValidator(bankAccount -> customerAcceptedAtmFee, FEE_ACCEPTED_MESSAGE);
// current amount
accountBinder.forField(currentAmount)
.withConverter(new StringToIntegerConverter("Whatever"))
.bind(BankAccount::getCurrentAmount, null);
// withdrawal amount
accountBinder.forField(withdrawalAmount)
.withConverter(new StringToIntegerConverter("Please enter a valid value"))
.withValidator(bean::hasEnoughMoneyForWithdrawal, "Not enough money")
.withValidator(value -> value > 0, "Please select a value greater than 0")
.asRequired("Please select withdrawal amount")
.bind(bankAccount -> TransactionForm.this.value, (bankAccount, value) -> TransactionForm.this.value = value);
// bind to bean
accountBinder.setBean(bean);
// show the modal and assign the call-back logic
Button saveButton = new Button("Save", event -> new ConfirmationWindow(this, Integer.valueOf(withdrawalAmount.getValue())).showModal(value -> {
// whether the client selected yes or no
customerAcceptedAtmFee = value;
// if all data selected, and client pressed "Ok", then execute the transaction
if (accountBinder.validate().isOk()) {
removeAllComponents();
addComponent(new Label("Transaction executed"));
}
}));
// disable the save button by default and enable it if
// the only validation error is the fact that the use has not yet accepted the fee
saveButton.setEnabled(false);
accountBinder.addStatusChangeListener(event -> {
saveButton.setEnabled(accountBinder.getStatusLabel().get().getValue().equals(FEE_ACCEPTED_MESSAGE));
});
// add fields to the UI
addComponents(currentAmount, withdrawalAmount, statusLabel, saveButton);
}
}
详细说明我的.drone.yaml文件:
{\"status\":\"error\",\"message\":\"%DBConnection.OwnershipError{message: \\\"cannot find ownership process for #PID<0.716.0>.\\\\n\\\\nWhen using ownership, you must manage connections in one\\\\nof the four ways:\\\\n\\\\n* By explicitly checking out a connection\\\\n* By explicitly allowing a spawned process\\\\n* By running the pool in shared mode\\\\n* By using :caller option with allowed process\\\\n\\\\nThe first two options require every new process to explicitly\\\\ncheck a connection out or be allowed by calling checkout or\\\\nallow respectively.\\\\n\\\\nThe third option requires a {:shared, pid} mode to be set.\\\\nIf using shared mode in tests, make sure your tests are not\\\\nasync.\\\\n\\\\nThe fourth option requires [caller: pid] to be used when\\\\nchecking out a connection from the pool. The caller process\\\\nshould already be allowed on a connection.\\\\n\\\\nIf you are reading this error, it means you have not done one\\\\nof the steps above or that the owner process has crashed.\\\\n\\\\nSee Ecto.Adapters.SQL.Sandbox docs for more information.\\\"}\",\"code\":0}"
每个应用中的 # Given the module FindUserByEmail
def Users.Services.FindUserByEmail do
use GenAMQP.Server, event: "find_user_by_email", conn_name:
Application.get_env(:gen_amqp, :conn_name)
alias User.Repo
alias User.Models.User, as: UserModel
def execute(payload) do
%{ "email" => email } = Poison.decode!(payload)
resp =
case Repo.get_by(UserModel, email: email) do
%UserModel{} = user -> %{status: :ok, response: user}
nil -> ErrorHelper.err(2011)
true -> ErrorHelper.err(2012)
{:error, %Ecto.Changeset{} = changeset} -> ViewHelper.translate_errors(changeset)
end
{:reply, Poison.encode!(resp)}
end
end
# and the test
defmodule Users.Services.FindUserByEmailTest do
use User.ModelCase
alias GenAMQP.Client
def execute(payload) do
resp = Client.call_with_conn(@conn_name, "find_user_by_email", payload)
data = Poison.decode!(resp, keys: :atoms)
assert data.status == "ok"
end
end
文件都包含以下别名
pipeline:
unit-tests:
image: bitwalker/alpine-elixir-phoenix:1.6.1
environment:
RABBITCONN: amqp://user:pass@localhost:0000/unit_testing
DATABASE_URL: ecto://username:password@postgres/testing
commands:
- mix local.hex --force && mix local.rebar --force
- mix deps.get
- mix compile --force
- mix test
我们所有mix.exs
个文件都包含以下配置:
defp aliases do
[
"test": ["ecto.create", "ecto.migrate", "test"]
]
end
我该如何调试?它只在测试容器内的代码时发生。这个问题会与集装箱的资源有关吗?
任何提示或提示都将受到赞赏。
答案 0 :(得分:0)
尝试将onwership_timeout
和timeout
设置为config/tests.exs
config :app_name, User.Repo,
adapter: Ecto.Adapters.Postgres,
username: ...,
password: ...,
database: ...,
hostname: ...,
pool: Ecto.Adapters.SQL.Sandbox,
timeout: 120_000, # i think the default is 5000
pool_timeout: 120_000,
ownership_timeout: 120_000 #i think the default is 5000